render: Don't use BitmapHandle in tessellator
Currently, we rely on ShapeTessellator being able to get a BitmapHandle without a RenderBackend. With the upcoming BitmapData refactor, we will always need a RenderBackend to get a BitmapHandle, which creates borrow-checker issues in ShapeTessellator (which is stored in a RenderBackend). To solve this, we split BitmapSource.bitmap into two methods - BitmapSource.bitmap and BitmapSource.bitmap_handle. ShapeTessellator continues to use BitmapSource.bitmap, and uses the u16 bitmap id instead of a BitmapHandle. The BitmapSource.bitmap_handle method is used inside each render backend to convert the id to a BitmapHandle, avoiding borrow-checker issues.
This commit is contained in:
parent
0aec23b468
commit
bdadb17a95
|
@ -1,7 +1,7 @@
|
|||
use crate::context::RenderContext;
|
||||
use gc_arena::Collect;
|
||||
use ruffle_render::backend::ShapeHandle;
|
||||
use ruffle_render::bitmap::{BitmapInfo, BitmapSource};
|
||||
use ruffle_render::backend::{RenderBackend, ShapeHandle};
|
||||
use ruffle_render::bitmap::{BitmapHandle, BitmapInfo, BitmapSize, BitmapSource};
|
||||
use ruffle_render::bounding_box::BoundingBox;
|
||||
use ruffle_render::commands::CommandHandler;
|
||||
use ruffle_render::shape_utils::{DistilledShape, DrawCommand, DrawPath};
|
||||
|
@ -402,8 +402,14 @@ impl Drawing {
|
|||
}
|
||||
|
||||
impl BitmapSource for Drawing {
|
||||
fn bitmap(&self, id: u16) -> Option<BitmapInfo> {
|
||||
self.bitmaps.get(id as usize).cloned()
|
||||
fn bitmap_size(&self, id: u16) -> Option<BitmapSize> {
|
||||
self.bitmaps.get(id as usize).map(|bm| BitmapSize {
|
||||
width: bm.width,
|
||||
height: bm.height,
|
||||
})
|
||||
}
|
||||
fn bitmap_handle(&self, id: u16, _backend: &mut dyn RenderBackend) -> Option<BitmapHandle> {
|
||||
self.bitmaps.get(id as usize).map(|bm| bm.handle)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ use crate::prelude::*;
|
|||
use crate::string::AvmString;
|
||||
use crate::tag_utils::SwfMovie;
|
||||
use gc_arena::{Collect, MutationContext};
|
||||
use ruffle_render::backend::RenderBackend;
|
||||
use ruffle_render::bitmap::BitmapHandle;
|
||||
use ruffle_render::utils::remove_invalid_jpeg_data;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
@ -315,14 +317,16 @@ impl<'gc> MovieLibrary<'gc> {
|
|||
}
|
||||
|
||||
impl<'gc> ruffle_render::bitmap::BitmapSource for MovieLibrary<'gc> {
|
||||
fn bitmap(&self, id: u16) -> Option<ruffle_render::bitmap::BitmapInfo> {
|
||||
self.get_bitmap(id).and_then(|bitmap| {
|
||||
Some(ruffle_render::bitmap::BitmapInfo {
|
||||
handle: bitmap.bitmap_handle()?,
|
||||
fn bitmap_size(&self, id: u16) -> Option<ruffle_render::bitmap::BitmapSize> {
|
||||
self.get_bitmap(id)
|
||||
.map(|bitmap| ruffle_render::bitmap::BitmapSize {
|
||||
width: bitmap.width(),
|
||||
height: bitmap.height(),
|
||||
})
|
||||
})
|
||||
}
|
||||
fn bitmap_handle(&self, id: u16, _backend: &mut dyn RenderBackend) -> Option<BitmapHandle> {
|
||||
self.get_bitmap(id)
|
||||
.and_then(|bitmap| bitmap.bitmap_handle())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -423,8 +423,7 @@ impl RenderBackend for WebCanvasRenderBackend {
|
|||
bitmap_source: &dyn BitmapSource,
|
||||
) -> ShapeHandle {
|
||||
let handle = ShapeHandle(self.shapes.len());
|
||||
let data =
|
||||
swf_shape_to_canvas_commands(&shape, bitmap_source, &self.bitmaps, &self.context);
|
||||
let data = swf_shape_to_canvas_commands(&shape, bitmap_source, self);
|
||||
self.shapes.push(data);
|
||||
handle
|
||||
}
|
||||
|
@ -435,8 +434,7 @@ impl RenderBackend for WebCanvasRenderBackend {
|
|||
bitmap_source: &dyn BitmapSource,
|
||||
handle: ShapeHandle,
|
||||
) {
|
||||
let data =
|
||||
swf_shape_to_canvas_commands(&shape, bitmap_source, &self.bitmaps, &self.context);
|
||||
let data = swf_shape_to_canvas_commands(&shape, bitmap_source, self);
|
||||
self.shapes[handle.0] = data;
|
||||
}
|
||||
|
||||
|
@ -810,8 +808,7 @@ fn draw_commands_to_path2d(commands: &[DrawCommand], is_closed: bool) -> Path2d
|
|||
fn swf_shape_to_canvas_commands(
|
||||
shape: &DistilledShape,
|
||||
bitmap_source: &dyn BitmapSource,
|
||||
bitmaps: &FnvHashMap<BitmapHandle, BitmapData>,
|
||||
context: &CanvasRenderingContext2d,
|
||||
backend: &mut WebCanvasRenderBackend,
|
||||
) -> ShapeData {
|
||||
use ruffle_render::shape_utils::DrawPath;
|
||||
use swf::{FillStyle, LineCapStyle, LineJoinStyle};
|
||||
|
@ -840,16 +837,21 @@ fn swf_shape_to_canvas_commands(
|
|||
let fill_style = match style {
|
||||
FillStyle::Color(color) => CanvasFillStyle::Color(color.into()),
|
||||
FillStyle::LinearGradient(gradient) => CanvasFillStyle::Gradient(
|
||||
create_linear_gradient(context, gradient, true).unwrap(),
|
||||
create_linear_gradient(&backend.context, gradient, true).unwrap(),
|
||||
),
|
||||
FillStyle::RadialGradient(gradient) => CanvasFillStyle::Gradient(
|
||||
create_radial_gradient(context, gradient, 0.0, true).unwrap(),
|
||||
create_radial_gradient(&backend.context, gradient, 0.0, true).unwrap(),
|
||||
),
|
||||
FillStyle::FocalGradient {
|
||||
gradient,
|
||||
focal_point,
|
||||
} => CanvasFillStyle::Gradient(
|
||||
create_radial_gradient(context, gradient, focal_point.to_f64(), true)
|
||||
create_radial_gradient(
|
||||
&backend.context,
|
||||
gradient,
|
||||
focal_point.to_f64(),
|
||||
true,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
FillStyle::Bitmap {
|
||||
|
@ -864,8 +866,7 @@ fn swf_shape_to_canvas_commands(
|
|||
*is_smoothed,
|
||||
*is_repeating,
|
||||
bitmap_source,
|
||||
bitmaps,
|
||||
context,
|
||||
backend,
|
||||
) {
|
||||
bitmap
|
||||
} else {
|
||||
|
@ -915,8 +916,7 @@ fn swf_shape_to_canvas_commands(
|
|||
*is_smoothed,
|
||||
*is_repeating,
|
||||
bitmap_source,
|
||||
bitmaps,
|
||||
context,
|
||||
backend,
|
||||
) {
|
||||
bitmap
|
||||
} else {
|
||||
|
@ -1159,12 +1159,11 @@ fn create_bitmap_pattern(
|
|||
is_smoothed: bool,
|
||||
is_repeating: bool,
|
||||
bitmap_source: &dyn BitmapSource,
|
||||
bitmaps: &FnvHashMap<BitmapHandle, BitmapData>,
|
||||
context: &CanvasRenderingContext2d,
|
||||
backend: &mut WebCanvasRenderBackend,
|
||||
) -> Option<CanvasBitmap> {
|
||||
if let Some(bitmap) = bitmap_source
|
||||
.bitmap(id)
|
||||
.and_then(|bitmap| bitmaps.get(&bitmap.handle))
|
||||
.bitmap_handle(id, backend)
|
||||
.and_then(|handle| backend.bitmaps.get(&handle))
|
||||
{
|
||||
let repeat = if !is_repeating {
|
||||
// NOTE: The WebGL backend does clamping in this case, just like
|
||||
|
@ -1174,7 +1173,9 @@ fn create_bitmap_pattern(
|
|||
"repeat"
|
||||
};
|
||||
|
||||
let pattern = match context.create_pattern_with_html_canvas_element(&bitmap.canvas, repeat)
|
||||
let pattern = match backend
|
||||
.context
|
||||
.create_pattern_with_html_canvas_element(&bitmap.canvas, repeat)
|
||||
{
|
||||
Ok(Some(pattern)) => pattern,
|
||||
_ => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::backend::{RenderBackend, ShapeHandle, ViewportDimensions};
|
||||
use crate::bitmap::{Bitmap, BitmapHandle, BitmapInfo, BitmapSource};
|
||||
use crate::bitmap::{Bitmap, BitmapHandle, BitmapSize, BitmapSource};
|
||||
use crate::commands::CommandList;
|
||||
use crate::error::Error;
|
||||
use crate::shape_utils::DistilledShape;
|
||||
|
@ -8,7 +8,10 @@ use swf::Color;
|
|||
pub struct NullBitmapSource;
|
||||
|
||||
impl BitmapSource for NullBitmapSource {
|
||||
fn bitmap(&self, _id: u16) -> Option<BitmapInfo> {
|
||||
fn bitmap_size(&self, _id: u16) -> Option<BitmapSize> {
|
||||
None
|
||||
}
|
||||
fn bitmap_handle(&self, _id: u16, _renderer: &mut dyn RenderBackend) -> Option<BitmapHandle> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use crate::backend::RenderBackend;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct BitmapHandle(pub usize);
|
||||
|
||||
|
@ -9,12 +11,19 @@ pub struct BitmapInfo {
|
|||
pub height: u16,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct BitmapSize {
|
||||
pub width: u16,
|
||||
pub height: u16,
|
||||
}
|
||||
|
||||
/// An object that returns a bitmap given an ID.
|
||||
///
|
||||
/// This is used by render backends to get the bitmap used in a bitmap fill.
|
||||
/// For movie libraries, this will return the bitmap with the given character ID.
|
||||
pub trait BitmapSource {
|
||||
fn bitmap(&self, id: u16) -> Option<BitmapInfo>;
|
||||
fn bitmap_size(&self, id: u16) -> Option<BitmapSize>;
|
||||
fn bitmap_handle(&self, id: u16, renderer: &mut dyn RenderBackend) -> Option<BitmapHandle>;
|
||||
}
|
||||
|
||||
/// Decoded bitmap data from an SWF tag.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::bitmap::{BitmapHandle, BitmapSource};
|
||||
use crate::bitmap::BitmapSource;
|
||||
use crate::shape_utils::{DistilledShape, DrawCommand, DrawPath};
|
||||
use lyon::path::Path;
|
||||
use lyon::tessellation::{
|
||||
|
@ -90,7 +90,7 @@ impl ShapeTessellator {
|
|||
is_smoothed,
|
||||
is_repeating,
|
||||
} => {
|
||||
if let Some(bitmap) = bitmap_source.bitmap(*id) {
|
||||
if let Some(bitmap) = bitmap_source.bitmap_size(*id) {
|
||||
(
|
||||
DrawType::Bitmap(Bitmap {
|
||||
matrix: swf_bitmap_to_gl_matrix(
|
||||
|
@ -98,7 +98,7 @@ impl ShapeTessellator {
|
|||
bitmap.width.into(),
|
||||
bitmap.height.into(),
|
||||
),
|
||||
bitmap: bitmap.handle,
|
||||
bitmap_id: *id,
|
||||
is_smoothed: *is_smoothed,
|
||||
is_repeating: *is_repeating,
|
||||
}),
|
||||
|
@ -264,7 +264,7 @@ pub struct Vertex {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct Bitmap {
|
||||
pub matrix: [[f32; 3]; 3],
|
||||
pub bitmap: BitmapHandle,
|
||||
pub bitmap_id: u16,
|
||||
pub is_smoothed: bool,
|
||||
pub is_repeating: bool,
|
||||
}
|
||||
|
|
|
@ -630,6 +630,8 @@ impl WebGlRenderBackend {
|
|||
.enable_vertex_attrib_array(program.vertex_color_location);
|
||||
}
|
||||
|
||||
let num_vertex_attributes = program.num_vertex_attributes;
|
||||
|
||||
draws.push(match draw.draw_type {
|
||||
TessDrawType::Color => Draw {
|
||||
draw_type: DrawType::Color,
|
||||
|
@ -662,7 +664,7 @@ impl WebGlRenderBackend {
|
|||
TessDrawType::Bitmap(bitmap) => Draw {
|
||||
draw_type: DrawType::Bitmap(BitmapDraw {
|
||||
matrix: bitmap.matrix,
|
||||
handle: bitmap.bitmap,
|
||||
handle: bitmap_source.bitmap_handle(bitmap.bitmap_id, self).unwrap(),
|
||||
is_smoothed: bitmap.is_smoothed,
|
||||
is_repeating: bitmap.is_repeating,
|
||||
}),
|
||||
|
@ -682,7 +684,8 @@ impl WebGlRenderBackend {
|
|||
|
||||
self.bind_vertex_array(None);
|
||||
|
||||
for i in program.num_vertex_attributes..NUM_VERTEX_ATTRIBUTES {
|
||||
// Don't use 'program' here in order to satisfy the borrow checker
|
||||
for i in num_vertex_attributes..NUM_VERTEX_ATTRIBUTES {
|
||||
self.gl.disable_vertex_attrib_array(i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,13 +200,7 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
|||
let mut draws = Vec::with_capacity(lyon_mesh.len());
|
||||
for draw in lyon_mesh {
|
||||
let draw_id = draws.len();
|
||||
draws.push(Draw::new(
|
||||
&self.descriptors,
|
||||
draw,
|
||||
shape_id,
|
||||
draw_id,
|
||||
&self.bitmap_registry,
|
||||
));
|
||||
draws.push(Draw::new(self, bitmap_source, draw, shape_id, draw_id));
|
||||
}
|
||||
|
||||
Mesh { draws }
|
||||
|
@ -223,6 +217,10 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
|||
pub fn device(&self) -> &wgpu::Device {
|
||||
&self.descriptors.device
|
||||
}
|
||||
|
||||
pub fn bitmap_registry(&self) -> &FnvHashMap<BitmapHandle, RegistryData> {
|
||||
&self.bitmap_registry
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use crate::backend::WgpuRenderBackend;
|
||||
use crate::target::RenderTarget;
|
||||
use crate::{
|
||||
create_buffer_with_data, Descriptors, GradientStorage, GradientUniforms, RegistryData,
|
||||
TextureTransforms, Vertex,
|
||||
create_buffer_with_data, Descriptors, GradientStorage, GradientUniforms, TextureTransforms,
|
||||
Vertex,
|
||||
};
|
||||
use fnv::FnvHashMap;
|
||||
use ruffle_render::bitmap::BitmapHandle;
|
||||
|
||||
use ruffle_render::bitmap::BitmapSource;
|
||||
use ruffle_render::tessellator::{Bitmap, Draw as LyonDraw, DrawType as TessDrawType, Gradient};
|
||||
use swf::CharacterId;
|
||||
|
||||
|
@ -22,14 +24,15 @@ pub struct Draw {
|
|||
}
|
||||
|
||||
impl Draw {
|
||||
pub fn new(
|
||||
descriptors: &Descriptors,
|
||||
pub fn new<T: RenderTarget>(
|
||||
backend: &mut WgpuRenderBackend<T>,
|
||||
source: &dyn BitmapSource,
|
||||
draw: LyonDraw,
|
||||
shape_id: CharacterId,
|
||||
draw_id: usize,
|
||||
bitmap_registry: &FnvHashMap<BitmapHandle, RegistryData>,
|
||||
) -> Self {
|
||||
let vertices: Vec<_> = draw.vertices.into_iter().map(Vertex::from).collect();
|
||||
let descriptors = backend.descriptors();
|
||||
let vertex_buffer = create_buffer_with_data(
|
||||
&descriptors.device,
|
||||
bytemuck::cast_slice(&vertices),
|
||||
|
@ -61,13 +64,7 @@ impl Draw {
|
|||
num_mask_indices: draw.mask_index_count,
|
||||
},
|
||||
TessDrawType::Bitmap(bitmap) => Draw {
|
||||
draw_type: DrawType::bitmap(
|
||||
&descriptors,
|
||||
&bitmap_registry,
|
||||
bitmap,
|
||||
shape_id,
|
||||
draw_id,
|
||||
),
|
||||
draw_type: DrawType::bitmap(backend, source, bitmap, shape_id, draw_id),
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
num_indices: index_count,
|
||||
|
@ -179,20 +176,23 @@ impl DrawType {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn bitmap(
|
||||
descriptors: &Descriptors,
|
||||
bitmap_registry: &FnvHashMap<BitmapHandle, RegistryData>,
|
||||
pub fn bitmap<T: RenderTarget>(
|
||||
backend: &mut WgpuRenderBackend<T>,
|
||||
source: &dyn BitmapSource,
|
||||
bitmap: Bitmap,
|
||||
shape_id: CharacterId,
|
||||
draw_id: usize,
|
||||
) -> Self {
|
||||
let entry = bitmap_registry.get(&bitmap.bitmap).unwrap();
|
||||
let bitmap_handle = source.bitmap_handle(bitmap.bitmap_id, backend).unwrap();
|
||||
let entry = backend.bitmap_registry().get(&bitmap_handle).unwrap();
|
||||
let descriptors = backend.descriptors();
|
||||
|
||||
let texture_view = entry
|
||||
.texture_wrapper
|
||||
.texture
|
||||
.create_view(&Default::default());
|
||||
let texture_transforms = create_texture_transforms(
|
||||
&descriptors.device,
|
||||
&backend.descriptors().device,
|
||||
&bitmap.matrix,
|
||||
create_debug_label!(
|
||||
"Shape {} draw {} textransforms ubo transfer buffer",
|
||||
|
|
Loading…
Reference in New Issue