2022-08-13 23:16:17 +00:00
|
|
|
pub mod null;
|
2022-08-13 22:12:24 +00:00
|
|
|
|
2023-01-07 16:08:23 +00:00
|
|
|
use crate::bitmap::{Bitmap, BitmapHandle, BitmapSource, SyncHandle};
|
2022-09-03 17:22:57 +00:00
|
|
|
use crate::commands::CommandList;
|
2022-08-13 23:16:17 +00:00
|
|
|
use crate::error::Error;
|
|
|
|
use crate::shape_utils::DistilledShape;
|
|
|
|
use downcast_rs::{impl_downcast, Downcast};
|
avm2: Partially implement Stage3D for wgpu backend
This PR implements core 'stage3D' APIs. We are now able
to render at least two demos from the Context3D docs - a simple
triangle render, and a rotating cube.
Implemented in this PR:
* Stage3D access and Context3D creation
* IndexBuffer3D and VertexBuffer3D creation, uploading, and usage
* Program3D uploading and usage (via `naga-agal`)
* Context3D: configureBackBuffer, clear, drawTriangles, and present
Not yet implemented:
* Any 'dispose()' methods
* Depth and stencil buffers
* Context3D texture apis
* Scissor rectangle
General implementation strategy:
A new `Object` variant is added for each of the Stage3D objects
(VertexBuffer3D, Program3D, etc). This stores a handle to the
parent `Context3D`, and (depending on the object) a handle
to the underlying native resource, via `Rc<dyn
SomeRenderBackendTrait>`).
Calling methods on Context3D does not usually result in an immediate
call to a `wgpu` method. Instead, we queue up commands in our
`Context3D` instance, and execute them all on a call to `present`.
This avoids some nasty wgpu lifetime issues, and is very similar
to the approah we use for normal rendering.
The actual rendering happens on a `Texture`, with dimensions
determined by `createBackBuffer`. During 'Stage' rendering,
we render all of these Stage3D textures *behind* the normal
stage (but in front of the overall stage background color).
2022-09-18 20:50:21 +00:00
|
|
|
use gc_arena::{Collect, GcCell, MutationContext};
|
2023-01-03 14:53:22 +00:00
|
|
|
use std::borrow::Cow;
|
avm2: Partially implement Stage3D for wgpu backend
This PR implements core 'stage3D' APIs. We are now able
to render at least two demos from the Context3D docs - a simple
triangle render, and a rotating cube.
Implemented in this PR:
* Stage3D access and Context3D creation
* IndexBuffer3D and VertexBuffer3D creation, uploading, and usage
* Program3D uploading and usage (via `naga-agal`)
* Context3D: configureBackBuffer, clear, drawTriangles, and present
Not yet implemented:
* Any 'dispose()' methods
* Depth and stencil buffers
* Context3D texture apis
* Scissor rectangle
General implementation strategy:
A new `Object` variant is added for each of the Stage3D objects
(VertexBuffer3D, Program3D, etc). This stores a handle to the
parent `Context3D`, and (depending on the object) a handle
to the underlying native resource, via `Rc<dyn
SomeRenderBackendTrait>`).
Calling methods on Context3D does not usually result in an immediate
call to a `wgpu` method. Instead, we queue up commands in our
`Context3D` instance, and execute them all on a call to `present`.
This avoids some nasty wgpu lifetime issues, and is very similar
to the approah we use for normal rendering.
The actual rendering happens on a `Texture`, with dimensions
determined by `createBackBuffer`. During 'Stage' rendering,
we render all of these Stage3D textures *behind* the normal
stage (but in front of the overall stage background color).
2022-09-18 20:50:21 +00:00
|
|
|
use std::rc::Rc;
|
2022-08-13 23:16:17 +00:00
|
|
|
use swf;
|
2019-08-26 23:38:37 +00:00
|
|
|
|
2020-05-11 07:02:49 +00:00
|
|
|
pub trait RenderBackend: Downcast {
|
2022-08-04 05:50:18 +00:00
|
|
|
fn viewport_dimensions(&self) -> ViewportDimensions;
|
|
|
|
// Do not call this method directly - use `player.set_viewport_dimensions`,
|
|
|
|
// which will ensure that the stage is properly updated as well.
|
|
|
|
fn set_viewport_dimensions(&mut self, dimensions: ViewportDimensions);
|
2020-12-30 23:35:43 +00:00
|
|
|
fn register_shape(
|
|
|
|
&mut self,
|
|
|
|
shape: DistilledShape,
|
2021-06-13 21:44:16 +00:00
|
|
|
bitmap_source: &dyn BitmapSource,
|
2020-12-30 23:35:43 +00:00
|
|
|
) -> ShapeHandle;
|
|
|
|
fn replace_shape(
|
|
|
|
&mut self,
|
|
|
|
shape: DistilledShape,
|
2021-06-13 21:44:16 +00:00
|
|
|
bitmap_source: &dyn BitmapSource,
|
2020-12-30 23:35:43 +00:00
|
|
|
handle: ShapeHandle,
|
|
|
|
);
|
2019-08-26 23:38:37 +00:00
|
|
|
fn register_glyph_shape(&mut self, shape: &swf::Glyph) -> ShapeHandle;
|
2022-05-27 19:16:33 +00:00
|
|
|
|
2022-09-06 21:38:48 +00:00
|
|
|
/// Creates a new `RenderBackend` which renders directly
|
|
|
|
/// to the texture specified by `BitmapHandle` with the given
|
|
|
|
/// `width` and `height`. This backend is passed to the callback
|
|
|
|
/// `f`, which performs the desired draw operations.
|
|
|
|
///
|
|
|
|
/// After the callback `f` exectures, the texture data is copied
|
|
|
|
/// from the GPU texture to an `RgbaImage`. There is no need to call
|
|
|
|
/// `update_texture` with the pixels from this image, as they
|
|
|
|
/// reflect data that is already stored on the GPU texture.
|
|
|
|
fn render_offscreen(
|
|
|
|
&mut self,
|
|
|
|
handle: BitmapHandle,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
2022-09-03 17:22:57 +00:00
|
|
|
commands: CommandList,
|
2023-01-07 16:08:23 +00:00
|
|
|
) -> Result<Box<dyn SyncHandle>, Error>;
|
|
|
|
|
2022-09-03 17:22:57 +00:00
|
|
|
fn submit_frame(&mut self, clear: swf::Color, commands: CommandList);
|
2022-07-25 16:31:40 +00:00
|
|
|
|
2022-05-27 19:16:33 +00:00
|
|
|
fn register_bitmap(&mut self, bitmap: Bitmap) -> Result<BitmapHandle, Error>;
|
2020-12-09 18:38:41 +00:00
|
|
|
fn update_texture(
|
|
|
|
&mut self,
|
2022-09-30 21:25:54 +00:00
|
|
|
bitmap: &BitmapHandle,
|
2020-12-09 18:38:41 +00:00
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
rgba: Vec<u8>,
|
2022-09-11 07:57:17 +00:00
|
|
|
) -> Result<(), Error>;
|
avm2: Partially implement Stage3D for wgpu backend
This PR implements core 'stage3D' APIs. We are now able
to render at least two demos from the Context3D docs - a simple
triangle render, and a rotating cube.
Implemented in this PR:
* Stage3D access and Context3D creation
* IndexBuffer3D and VertexBuffer3D creation, uploading, and usage
* Program3D uploading and usage (via `naga-agal`)
* Context3D: configureBackBuffer, clear, drawTriangles, and present
Not yet implemented:
* Any 'dispose()' methods
* Depth and stencil buffers
* Context3D texture apis
* Scissor rectangle
General implementation strategy:
A new `Object` variant is added for each of the Stage3D objects
(VertexBuffer3D, Program3D, etc). This stores a handle to the
parent `Context3D`, and (depending on the object) a handle
to the underlying native resource, via `Rc<dyn
SomeRenderBackendTrait>`).
Calling methods on Context3D does not usually result in an immediate
call to a `wgpu` method. Instead, we queue up commands in our
`Context3D` instance, and execute them all on a call to `present`.
This avoids some nasty wgpu lifetime issues, and is very similar
to the approah we use for normal rendering.
The actual rendering happens on a `Texture`, with dimensions
determined by `createBackBuffer`. During 'Stage' rendering,
we render all of these Stage3D textures *behind* the normal
stage (but in front of the overall stage background color).
2022-09-18 20:50:21 +00:00
|
|
|
|
|
|
|
fn create_context3d(&mut self) -> Result<Box<dyn Context3D>, Error>;
|
|
|
|
fn context3d_present<'gc>(
|
|
|
|
&mut self,
|
|
|
|
context: &mut dyn Context3D,
|
|
|
|
commands: Vec<Context3DCommand<'gc>>,
|
|
|
|
mc: MutationContext<'gc, '_>,
|
|
|
|
) -> Result<(), Error>;
|
2023-01-03 14:53:22 +00:00
|
|
|
|
|
|
|
fn debug_info(&self) -> Cow<'static, str>;
|
2019-08-26 23:38:37 +00:00
|
|
|
}
|
2020-05-11 07:02:49 +00:00
|
|
|
impl_downcast!(RenderBackend);
|
2019-08-26 23:38:37 +00:00
|
|
|
|
avm2: Partially implement Stage3D for wgpu backend
This PR implements core 'stage3D' APIs. We are now able
to render at least two demos from the Context3D docs - a simple
triangle render, and a rotating cube.
Implemented in this PR:
* Stage3D access and Context3D creation
* IndexBuffer3D and VertexBuffer3D creation, uploading, and usage
* Program3D uploading and usage (via `naga-agal`)
* Context3D: configureBackBuffer, clear, drawTriangles, and present
Not yet implemented:
* Any 'dispose()' methods
* Depth and stencil buffers
* Context3D texture apis
* Scissor rectangle
General implementation strategy:
A new `Object` variant is added for each of the Stage3D objects
(VertexBuffer3D, Program3D, etc). This stores a handle to the
parent `Context3D`, and (depending on the object) a handle
to the underlying native resource, via `Rc<dyn
SomeRenderBackendTrait>`).
Calling methods on Context3D does not usually result in an immediate
call to a `wgpu` method. Instead, we queue up commands in our
`Context3D` instance, and execute them all on a call to `present`.
This avoids some nasty wgpu lifetime issues, and is very similar
to the approah we use for normal rendering.
The actual rendering happens on a `Texture`, with dimensions
determined by `createBackBuffer`. During 'Stage' rendering,
we render all of these Stage3D textures *behind* the normal
stage (but in front of the overall stage background color).
2022-09-18 20:50:21 +00:00
|
|
|
pub trait IndexBuffer: Downcast + Collect {}
|
|
|
|
impl_downcast!(IndexBuffer);
|
|
|
|
pub trait VertexBuffer: Downcast + Collect {}
|
|
|
|
impl_downcast!(VertexBuffer);
|
|
|
|
|
|
|
|
pub trait ShaderModule: Downcast + Collect {}
|
|
|
|
impl_downcast!(ShaderModule);
|
|
|
|
|
|
|
|
#[derive(Collect)]
|
|
|
|
#[collect(require_static)]
|
|
|
|
pub enum BufferUsage {
|
|
|
|
DynamicDraw,
|
|
|
|
StaticDraw,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Collect)]
|
|
|
|
#[collect(require_static)]
|
|
|
|
pub enum ProgramType {
|
|
|
|
Vertex,
|
|
|
|
Fragment,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait Context3D: Collect + Downcast {
|
|
|
|
// The BitmapHandle for the texture we're rendering to
|
|
|
|
fn bitmap_handle(&self) -> BitmapHandle;
|
|
|
|
// Whether or not we should actually render the texture
|
|
|
|
// as part of stage rendering
|
|
|
|
fn should_render(&self) -> bool;
|
|
|
|
|
|
|
|
// Get a 'disposed' handle - this is what we store in all IndexBuffer3D
|
|
|
|
// objects after dispose() has been called.
|
|
|
|
fn disposed_index_buffer_handle(&self) -> Rc<dyn IndexBuffer>;
|
|
|
|
|
|
|
|
// Get a 'disposed' handle - this is what we store in all VertexBuffer3D
|
|
|
|
// objects after dispose() has been called.
|
|
|
|
fn disposed_vertex_buffer_handle(&self) -> Rc<dyn VertexBuffer>;
|
|
|
|
|
|
|
|
fn create_index_buffer(&mut self, usage: BufferUsage, num_indices: u32) -> Rc<dyn IndexBuffer>;
|
|
|
|
fn create_vertex_buffer(
|
|
|
|
&mut self,
|
|
|
|
usage: BufferUsage,
|
|
|
|
num_vertices: u32,
|
|
|
|
vertex_size: u32,
|
|
|
|
) -> Rc<dyn VertexBuffer>;
|
|
|
|
}
|
|
|
|
impl_downcast!(Context3D);
|
|
|
|
|
|
|
|
#[derive(Collect, Copy, Clone, Debug)]
|
|
|
|
#[collect(require_static)]
|
|
|
|
pub enum Context3DVertexBufferFormat {
|
|
|
|
Float1,
|
|
|
|
Float2,
|
|
|
|
Float3,
|
|
|
|
Float4,
|
|
|
|
Bytes4,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Collect, Copy, Clone, Debug)]
|
|
|
|
#[collect(require_static)]
|
|
|
|
pub enum Context3DTriangleFace {
|
|
|
|
None,
|
|
|
|
Back,
|
|
|
|
Front,
|
|
|
|
FrontAndBack,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Collect)]
|
|
|
|
#[collect(no_drop)]
|
|
|
|
pub enum Context3DCommand<'gc> {
|
|
|
|
Clear {
|
|
|
|
red: f64,
|
|
|
|
green: f64,
|
|
|
|
blue: f64,
|
|
|
|
alpha: f64,
|
|
|
|
depth: f64,
|
|
|
|
stencil: u32,
|
|
|
|
mask: u32,
|
|
|
|
},
|
|
|
|
ConfigureBackBuffer {
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
anti_alias: u32,
|
|
|
|
depth_and_stencil: bool,
|
|
|
|
wants_best_resolution: bool,
|
|
|
|
wants_best_resolution_on_browser_zoom: bool,
|
|
|
|
},
|
|
|
|
|
|
|
|
UploadToIndexBuffer {
|
|
|
|
buffer: Rc<dyn IndexBuffer>,
|
|
|
|
start_offset: usize,
|
|
|
|
data: Vec<u8>,
|
|
|
|
},
|
|
|
|
|
|
|
|
UploadToVertexBuffer {
|
|
|
|
buffer: Rc<dyn VertexBuffer>,
|
|
|
|
start_vertex: usize,
|
|
|
|
data_per_vertex: usize,
|
|
|
|
data: Vec<u8>,
|
|
|
|
},
|
|
|
|
|
|
|
|
DrawTriangles {
|
|
|
|
index_buffer: Rc<dyn IndexBuffer>,
|
|
|
|
first_index: usize,
|
|
|
|
num_triangles: isize,
|
|
|
|
},
|
|
|
|
|
|
|
|
SetVertexBufferAt {
|
|
|
|
index: u32,
|
|
|
|
buffer: Rc<dyn VertexBuffer>,
|
|
|
|
buffer_offset: u32,
|
|
|
|
format: Context3DVertexBufferFormat,
|
|
|
|
},
|
|
|
|
|
|
|
|
UploadShaders {
|
|
|
|
vertex_shader: GcCell<'gc, Option<Rc<dyn ShaderModule>>>,
|
|
|
|
vertex_shader_agal: Vec<u8>,
|
|
|
|
fragment_shader: GcCell<'gc, Option<Rc<dyn ShaderModule>>>,
|
|
|
|
fragment_shader_agal: Vec<u8>,
|
|
|
|
},
|
|
|
|
|
|
|
|
SetShaders {
|
|
|
|
vertex_shader: GcCell<'gc, Option<Rc<dyn ShaderModule>>>,
|
|
|
|
fragment_shader: GcCell<'gc, Option<Rc<dyn ShaderModule>>>,
|
|
|
|
},
|
|
|
|
SetProgramConstantsFromVector {
|
|
|
|
program_type: ProgramType,
|
|
|
|
first_register: u32,
|
|
|
|
matrix_raw_data_column_major: Vec<f32>,
|
|
|
|
},
|
|
|
|
SetCulling {
|
|
|
|
face: Context3DTriangleFace,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-08-26 23:38:37 +00:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub struct ShapeHandle(pub usize);
|
2022-08-04 05:50:18 +00:00
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub struct ViewportDimensions {
|
|
|
|
/// The dimensions of the stage's containing viewport.
|
|
|
|
pub width: u32,
|
|
|
|
pub height: u32,
|
|
|
|
|
|
|
|
/// The scale factor of the containing viewport from standard-size pixels
|
|
|
|
/// to device-scale pixels.
|
|
|
|
pub scale_factor: f64,
|
|
|
|
}
|