diff --git a/core/src/avm1/globals/bitmap_data.rs b/core/src/avm1/globals/bitmap_data.rs index 038107780f2d..b7c40b81ad6c 100644 --- a/core/src/avm1/globals/bitmap_data.rs +++ b/core/src/avm1/globals/bitmap_data.rs @@ -7,7 +7,7 @@ use crate::avm1::globals::color_transform::ColorTransformObject; use crate::avm1::object::NativeObject; use crate::avm1::property_decl::{define_properties_on, Declaration}; use crate::avm1::{Activation, Attribute, Error, Object, ScriptObject, TObject, Value}; -use crate::bitmap::bitmap_data::{BitmapData, BitmapDataWrapper}; +use crate::bitmap::bitmap_data::BitmapData; use crate::bitmap::bitmap_data::{BitmapDataDrawError, IBitmapDrawable}; use crate::bitmap::bitmap_data::{ChannelOptions, ThresholdOperation}; use crate::bitmap::{is_size_valid, operations}; @@ -16,7 +16,7 @@ use crate::display_object::DisplayObject; use crate::string::StringContext; use crate::swf::BlendMode; use crate::{avm1_stub, avm_error}; -use gc_arena::{GcCell, Mutation}; +use gc_arena::Mutation; use ruffle_render::transform::Transform; const PROTO_DECLS: &[Declaration] = declare_properties! { @@ -70,10 +70,7 @@ fn new_bitmap_data<'gc>( Attribute::DONT_ENUM | Attribute::DONT_DELETE, ); } - object.set_native( - gc_context, - NativeObject::BitmapData(BitmapDataWrapper::new(GcCell::new(gc_context, bitmap_data))), - ); + object.set_native(gc_context, NativeObject::BitmapData(bitmap_data)); object } @@ -103,13 +100,16 @@ fn constructor<'gc>( return Ok(Value::Undefined); } - let bitmap_data = BitmapData::new(width, height, transparency, fill_color); + let bitmap_data = BitmapData::new( + activation.context.gc_context, + width, + height, + transparency, + fill_color, + ); this.set_native( activation.context.gc_context, - NativeObject::BitmapData(BitmapDataWrapper::new(GcCell::new( - activation.context.gc_context, - bitmap_data, - ))), + NativeObject::BitmapData(bitmap_data), ); Ok(this.into()) } @@ -405,7 +405,7 @@ fn clone<'gc>( return Ok(new_bitmap_data( activation.context.gc_context, this.get_local_stored("__proto__", activation, false), - bitmap_data.clone_data(activation.context.renderer), + bitmap_data.clone_data(activation.context.gc_context, activation.context.renderer), ) .into()); } @@ -1464,6 +1464,7 @@ fn compare<'gc>( } match operations::compare( + activation.context.gc_context, activation.context.renderer, this_bitmap_data, other_bitmap_data, @@ -1505,6 +1506,7 @@ fn load_bitmap<'gc>( let transparency = true; let bitmap_data = BitmapData::new_with_pixels( + activation.context.gc_context, bitmap.width(), bitmap.height(), transparency, diff --git a/core/src/avm1/globals/displacement_map_filter.rs b/core/src/avm1/globals/displacement_map_filter.rs index 68a9e216a7fc..edf1b760a9b3 100644 --- a/core/src/avm1/globals/displacement_map_filter.rs +++ b/core/src/avm1/globals/displacement_map_filter.rs @@ -5,7 +5,7 @@ use crate::avm1::function::{Executable, FunctionObject}; use crate::avm1::object::NativeObject; use crate::avm1::property_decl::{define_properties_on, Declaration}; use crate::avm1::{Activation, Error, Object, ScriptObject, TObject, Value}; -use crate::bitmap::bitmap_data::BitmapDataWrapper; +use crate::bitmap::bitmap_data::BitmapData; use crate::context::UpdateContext; use crate::string::{AvmString, FromWStr, StringContext, WStr}; use gc_arena::{Collect, GcCell, Mutation}; @@ -77,7 +77,7 @@ impl From for DisplacementMapFilterMode { #[derive(Clone, Collect, Debug, Default)] #[collect(no_drop)] struct DisplacementMapFilterData<'gc> { - map_bitmap: Option>, + map_bitmap: Option>, #[collect(require_static)] map_point: Point, component_x: i32, diff --git a/core/src/avm1/object.rs b/core/src/avm1/object.rs index 14bed97ef75c..f3c73b7775ae 100644 --- a/core/src/avm1/object.rs +++ b/core/src/avm1/object.rs @@ -22,7 +22,7 @@ use crate::avm1::globals::xml_socket::XmlSocket; use crate::avm1::object::array_object::ArrayObject; use crate::avm1::object::super_object::SuperObject; use crate::avm1::{Activation, Attribute, Error, ScriptObject, StageObject, Value}; -use crate::bitmap::bitmap_data::BitmapDataWrapper; +use crate::bitmap::bitmap_data::BitmapData; use crate::display_object::DisplayObject; use crate::display_object::TDisplayObject; use crate::html::TextFormat; @@ -61,7 +61,7 @@ pub enum NativeObject<'gc> { Transform(TransformObject<'gc>), TextFormat(Gc<'gc, RefCell>), NetStream(NetStream<'gc>), - BitmapData(BitmapDataWrapper<'gc>), + BitmapData(BitmapData<'gc>), Xml(Xml<'gc>), XmlNode(XmlNode<'gc>), SharedObject(GcCell<'gc, SharedObject>), diff --git a/core/src/avm2/globals/flash/display/bitmap.rs b/core/src/avm2/globals/flash/display/bitmap.rs index 29c0b1647062..9f1c9f4dd33f 100644 --- a/core/src/avm2/globals/flash/display/bitmap.rs +++ b/core/src/avm2/globals/flash/display/bitmap.rs @@ -11,7 +11,7 @@ use ruffle_wstr::WStr; use crate::avm2::error::make_error_2008; use crate::avm2::parameters::ParametersExt; -use crate::bitmap::bitmap_data::BitmapDataWrapper; +use crate::bitmap::bitmap_data::BitmapData; use crate::character::Character; use crate::display_object::{Bitmap, TDisplayObject}; @@ -26,7 +26,7 @@ pub fn bitmap_allocator<'gc>( let orig_class = class; while let Some(class) = class_def { if class == bitmap_cls { - let bitmap_data = BitmapDataWrapper::dummy(activation.context.gc_context); + let bitmap_data = BitmapData::dummy(activation.context.gc_context); let display_object = Bitmap::new_with_bitmap_data( activation.context.gc_context, 0, @@ -58,7 +58,7 @@ pub fn bitmap_allocator<'gc>( let new_bitmap_data = fill_bitmap_data_from_symbol(activation, &compressed); let bitmap_data_obj = BitmapDataObject::from_bitmap_data_internal( activation, - BitmapDataWrapper::dummy(activation.context.gc_context), + BitmapData::dummy(activation.context.gc_context), bitmapdata_cls, )?; bitmap_data_obj.init_bitmap_data(activation.context.gc_context, new_bitmap_data); @@ -116,7 +116,7 @@ pub fn get_bitmap_data<'gc>( _args: &[Value<'gc>], ) -> Result, Error<'gc>> { if let Some(bitmap) = this.as_display_object().and_then(|dobj| dobj.as_bitmap()) { - let mut value = bitmap.bitmap_data_wrapper().object2(); + let mut value = bitmap.bitmap_data().object2(); // AS3 expects an unset BitmapData to be null, not 'undefined' if matches!(value, Value::Undefined) { @@ -141,7 +141,7 @@ pub fn set_bitmap_data<'gc>( bitmap_data.as_bitmap_data().expect("Must be a BitmapData") } else { // Passing null results in a dummy BitmapData being set. - BitmapDataWrapper::dummy(activation.gc()) + BitmapData::dummy(activation.gc()) }; bitmap.set_bitmap_data(activation.context, bitmap_data); diff --git a/core/src/avm2/globals/flash/display/bitmap_data.rs b/core/src/avm2/globals/flash/display/bitmap_data.rs index 3f80851b339b..3ebdf3ea313c 100644 --- a/core/src/avm2/globals/flash/display/bitmap_data.rs +++ b/core/src/avm2/globals/flash/display/bitmap_data.rs @@ -13,16 +13,13 @@ use crate::avm2::value::Value; use crate::avm2::vector::VectorStorage; use crate::avm2::Error; use crate::avm2_stub_method; -use crate::bitmap::bitmap_data::{ - BitmapData, BitmapDataWrapper, ChannelOptions, ThresholdOperation, -}; +use crate::bitmap::bitmap_data::{BitmapData, ChannelOptions, ThresholdOperation}; use crate::bitmap::bitmap_data::{BitmapDataDrawError, IBitmapDrawable}; use crate::bitmap::{is_size_valid, operations}; use crate::character::{Character, CompressedBitmap}; use crate::display_object::TDisplayObject; use crate::ecma_conversions::round_to_even; use crate::swf::BlendMode; -use gc_arena::GcCell; use ruffle_render::filters::Filter; use ruffle_render::transform::Transform; use std::str::FromStr; @@ -69,21 +66,18 @@ fn get_rectangle_x_y_width_height<'gc>( pub fn fill_bitmap_data_from_symbol<'gc>( activation: &mut Activation<'_, 'gc>, bd: &CompressedBitmap, -) -> BitmapDataWrapper<'gc> { +) -> BitmapData<'gc> { let bitmap = bd.decode().expect("Failed to decode BitmapData"); - let new_bitmap_data = GcCell::new( + BitmapData::new_with_pixels( activation.context.gc_context, - BitmapData::new_with_pixels( - bitmap.width(), - bitmap.height(), - true, - bitmap - .as_colors() - .map(crate::bitmap::bitmap_data::Color::from) - .collect(), - ), - ); - BitmapDataWrapper::new(new_bitmap_data) + bitmap.width(), + bitmap.height(), + true, + bitmap + .as_colors() + .map(crate::bitmap::bitmap_data::Color::from) + .collect(), + ) } /// Implements `flash.display.BitmapData`'s 'init' method (invoked from the AS3 constructor) @@ -92,7 +86,7 @@ pub fn init<'gc>( this: Object<'gc>, args: &[Value<'gc>], ) -> Result, Error<'gc>> { - // We set the underlying BitmapData instance - we start out with a dummy BitmapDataWrapper, + // We set the underlying BitmapData instance - we start out with a dummy BitmapData, // which makes custom classes see a disposed BitmapData before they call super() let name = this.instance_class().name(); let character = activation @@ -140,8 +134,13 @@ pub fn init<'gc>( )?)); } - let new_bitmap_data = BitmapData::new(width, height, transparency, fill_color); - BitmapDataWrapper::new(GcCell::new(activation.context.gc_context, new_bitmap_data)) + BitmapData::new( + activation.context.gc_context, + width, + height, + transparency, + fill_color, + ) }; new_bitmap_data.init_object2(activation.context.gc_context, this); @@ -842,7 +841,7 @@ pub fn hit_test<'gc>( .as_display_object() .and_then(|dobj| dobj.as_bitmap()) { - let other_bmd = bitmap.bitmap_data_wrapper(); + let other_bmd = bitmap.bitmap_data(); other_bmd.check_valid(activation)?; let second_point = args.get_object(activation, 3, "secondBitmapDataPoint")?; let second_point = ( @@ -1192,14 +1191,12 @@ pub fn clone<'gc>( ) -> Result, Error<'gc>> { if let Some(bitmap_data) = this.as_bitmap_data() { if !bitmap_data.disposed() { - let new_bitmap_data = bitmap_data.clone_data(activation.context.renderer); + let new_bitmap_data = + bitmap_data.clone_data(activation.context.gc_context, activation.context.renderer); let class = activation.avm2().classes().bitmapdata; - let new_bitmap_data_object = BitmapDataObject::from_bitmap_data_internal( - activation, - BitmapDataWrapper::new(GcCell::new(activation.context.gc_context, new_bitmap_data)), - class, - )?; + let new_bitmap_data_object = + BitmapDataObject::from_bitmap_data_internal(activation, new_bitmap_data, class)?; return Ok(new_bitmap_data_object.into()); } @@ -1457,18 +1454,14 @@ pub fn compare<'gc>( } match operations::compare( + activation.context.gc_context, activation.context.renderer, this_bitmap_data, other_bitmap_data, ) { Some(bitmap_data) => { let class = activation.avm2().classes().bitmapdata; - Ok(BitmapDataObject::from_bitmap_data_internal( - activation, - BitmapDataWrapper::new(GcCell::new(activation.context.gc_context, bitmap_data)), - class, - )? - .into()) + Ok(BitmapDataObject::from_bitmap_data_internal(activation, bitmap_data, class)?.into()) } None => Ok(EQUIVALENT.into()), } diff --git a/core/src/avm2/globals/flash/display3D/textures/texture.rs b/core/src/avm2/globals/flash/display3D/textures/texture.rs index 8adaeee2715c..d1731c0c9867 100644 --- a/core/src/avm2/globals/flash/display3D/textures/texture.rs +++ b/core/src/avm2/globals/flash/display3D/textures/texture.rs @@ -1,5 +1,3 @@ -use gc_arena::GcCell; - use ruffle_render::backend::Context3DTextureFormat; use super::atf_jpegxr::do_compressed_upload; @@ -11,7 +9,6 @@ use crate::avm2::Value; use crate::avm2::{Error, Object}; use crate::avm2_stub_method; use crate::bitmap::bitmap_data::BitmapData; -use crate::bitmap::bitmap_data::BitmapDataWrapper; use crate::bitmap::bitmap_data::Color; pub fn do_copy<'gc>( @@ -32,7 +29,7 @@ pub fn do_copy<'gc>( return Ok(()); } - // FIXME - see if we can avoid this intermediate BitmapDataWrapper, and copy + // FIXME - see if we can avoid this intermediate BitmapData, and copy // directly from a buffer to the target GPU texture let bitmap_data = match texture.original_format() { Context3DTextureFormat::Bgra => { @@ -51,8 +48,7 @@ pub fn do_copy<'gc>( }) .collect(); - let bitmap_data = BitmapData::new_with_pixels(width, height, true, colors); - BitmapDataWrapper::new(GcCell::new(activation.context.gc_context, bitmap_data)) + BitmapData::new_with_pixels(activation.context.gc_context, width, height, true, colors) } _ => { tracing::warn!( diff --git a/core/src/avm2/object.rs b/core/src/avm2/object.rs index 741ff8df29ab..e9c925023e1d 100644 --- a/core/src/avm2/object.rs +++ b/core/src/avm2/object.rs @@ -16,7 +16,7 @@ use crate::avm2::vtable::{ClassBoundMethod, VTable}; use crate::avm2::Error; use crate::avm2::Multiname; use crate::avm2::Namespace; -use crate::bitmap::bitmap_data::BitmapDataWrapper; +use crate::bitmap::bitmap_data::BitmapData; use crate::display_object::DisplayObject; use crate::html::TextFormat; use crate::streams::NetStream; @@ -1259,7 +1259,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy None } - fn as_bitmap_data(&self) -> Option> { + fn as_bitmap_data(&self) -> Option> { None } @@ -1273,7 +1273,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy /// This should only be called to initialize the association between an AVM /// object and it's associated bitmap data. This association should not be /// reinitialized later. - fn init_bitmap_data(&self, _mc: &Mutation<'gc>, _new_bitmap: BitmapDataWrapper<'gc>) {} + fn init_bitmap_data(&self, _mc: &Mutation<'gc>, _new_bitmap: BitmapData<'gc>) {} /// Get this objects `DateObject`, if it has one. fn as_date_object(&self) -> Option> { diff --git a/core/src/avm2/object/bitmapdata_object.rs b/core/src/avm2/object/bitmapdata_object.rs index 245866f67e78..3e0bf4d2807e 100644 --- a/core/src/avm2/object/bitmapdata_object.rs +++ b/core/src/avm2/object/bitmapdata_object.rs @@ -4,7 +4,7 @@ use crate::avm2::activation::Activation; use crate::avm2::object::script_object::ScriptObjectData; use crate::avm2::object::{ClassObject, Object, ObjectPtr, TObject}; use crate::avm2::Error; -use crate::bitmap::bitmap_data::BitmapDataWrapper; +use crate::bitmap::bitmap_data::BitmapData; use core::fmt; use gc_arena::barrier::unlock; use gc_arena::{lock::Lock, Collect, Gc, GcWeak, Mutation}; @@ -20,12 +20,10 @@ pub fn bitmap_data_allocator<'gc>( activation.context.gc_context, BitmapDataObjectData { base, - // This always starts out as a dummy (invalid) BitmapDataWrapper, so + // This always starts out as a dummy (invalid) BitmapData, so // that custom subclasses see a disposed BitmapData before they call super(). - // The real BitmapDataWrapper is set by BitmapData.init() - bitmap_data: Lock::new(Some(BitmapDataWrapper::dummy( - activation.context.gc_context, - ))), + // The real BitmapData is set by BitmapData.init() + bitmap_data: Lock::new(Some(BitmapData::dummy(activation.context.gc_context))), }, )) .into()) @@ -54,7 +52,7 @@ pub struct BitmapDataObjectData<'gc> { /// Base script object base: ScriptObjectData<'gc>, - bitmap_data: Lock>>, + bitmap_data: Lock>>, } const _: () = assert!(std::mem::offset_of!(BitmapDataObjectData, base) == 0); @@ -63,7 +61,7 @@ const _: () = assert!( ); impl<'gc> BitmapDataObject<'gc> { - // Constructs a BitmapData object from a BitmapDataWrapper. + // Constructs a BitmapData object from a BitmapData. // This is *not* used when explicitly constructing a BitmapData // instance from ActionScript (e.g. `new BitmapData(100, 100)`, // or `new MyBitmapDataSubclass(100, 100)`). @@ -74,7 +72,7 @@ impl<'gc> BitmapDataObject<'gc> { // like `clone()` pub fn from_bitmap_data_internal( activation: &mut Activation<'_, 'gc>, - bitmap_data: BitmapDataWrapper<'gc>, + bitmap_data: BitmapData<'gc>, class: ClassObject<'gc>, ) -> Result, Error<'gc>> { let instance: Object<'gc> = Self(Gc::new( @@ -114,13 +112,13 @@ impl<'gc> TObject<'gc> for BitmapDataObject<'gc> { Gc::as_ptr(self.0) as *const ObjectPtr } - fn as_bitmap_data(&self) -> Option> { + fn as_bitmap_data(&self) -> Option> { self.0.bitmap_data.get() } /// Initialize the bitmap data in this object, if it's capable of /// supporting said data - fn init_bitmap_data(&self, mc: &Mutation<'gc>, new_bitmap: BitmapDataWrapper<'gc>) { + fn init_bitmap_data(&self, mc: &Mutation<'gc>, new_bitmap: BitmapData<'gc>) { unlock!(Gc::write(mc, self.0), BitmapDataObjectData, bitmap_data).set(Some(new_bitmap)); } } diff --git a/core/src/avm2/object/context3d_object.rs b/core/src/avm2/object/context3d_object.rs index 3cb046e9165e..de889c6e183d 100644 --- a/core/src/avm2/object/context3d_object.rs +++ b/core/src/avm2/object/context3d_object.rs @@ -6,7 +6,7 @@ use crate::avm2::object::{Object, ObjectPtr, TObject}; use crate::avm2::value::Value; use crate::avm2::Error; use crate::avm2_stub_method; -use crate::bitmap::bitmap_data::BitmapData; +use crate::bitmap::bitmap_data::BitmapRawData; use crate::context::RenderContext; use gc_arena::{Collect, Gc, GcCell, GcWeak}; use ruffle_render::backend::{ @@ -344,7 +344,7 @@ impl<'gc> Context3DObject<'gc> { } pub(crate) fn copy_bitmapdata_to_texture( &self, - source: GcCell<'gc, BitmapData<'gc>>, + source: GcCell<'gc, BitmapRawData<'gc>>, dest: Rc, layer: u32, ) { diff --git a/core/src/bitmap/bitmap_data.rs b/core/src/bitmap/bitmap_data.rs index ea2b118c50a8..567ca0f09a39 100644 --- a/core/src/bitmap/bitmap_data.rs +++ b/core/src/bitmap/bitmap_data.rs @@ -1,10 +1,14 @@ use crate::avm2::{Object as Avm2Object, Value as Avm2Value}; +use crate::context::RenderContext; use crate::display_object::{DisplayObject, DisplayObjectWeak, TDisplayObject}; use bitflags::bitflags; -use gc_arena::{Collect, Mutation}; +use gc_arena::{Collect, GcCell, Mutation}; use ruffle_render::backend::RenderBackend; -use ruffle_render::bitmap::{Bitmap, BitmapFormat, BitmapHandle, PixelRegion, SyncHandle}; +use ruffle_render::bitmap::{ + Bitmap, BitmapFormat, BitmapHandle, PixelRegion, PixelSnapping, SyncHandle, +}; use ruffle_wstr::WStr; +use std::cell::Ref; use std::fmt::Debug; use std::ops::Range; use swf::{Rectangle, Twips}; @@ -192,9 +196,151 @@ bitflags! { } } +#[derive(Copy, Clone, Collect, Debug)] +#[collect(no_drop)] +pub struct BitmapData<'gc>(BitmapRawDataWrapper<'gc>); + +impl<'gc> BitmapData<'gc> { + pub fn new( + mc: &Mutation<'gc>, + width: u32, + height: u32, + transparency: bool, + fill_color: u32, + ) -> Self { + let data = BitmapRawData::new(width, height, transparency, fill_color); + let data = BitmapRawDataWrapper::new(GcCell::new(mc, data)); + + Self(data) + } + + pub fn new_with_pixels( + mc: &Mutation<'gc>, + width: u32, + height: u32, + transparency: bool, + pixels: Vec, + ) -> Self { + let data = BitmapRawData::new_with_pixels(width, height, transparency, pixels); + let data = BitmapRawDataWrapper::new(GcCell::new(mc, data)); + + Self(data) + } + + pub fn dummy(mc: &Mutation<'gc>) -> Self { + Self(BitmapRawDataWrapper::dummy(mc)) + } + + pub fn clone_data( + &self, + mc: &Mutation<'gc>, + renderer: &mut dyn RenderBackend, + ) -> BitmapData<'gc> { + let data = self.0.clone_data(renderer); + let data = BitmapRawDataWrapper::new(GcCell::new(mc, data)); + Self(data) + } + + pub fn sync(&self, renderer: &mut dyn RenderBackend) -> GcCell<'gc, BitmapRawData<'gc>> { + self.0.sync(renderer) + } + + pub fn bitmap_handle( + &self, + gc_context: &Mutation<'gc>, + renderer: &mut dyn RenderBackend, + ) -> BitmapHandle { + self.0.bitmap_handle(gc_context, renderer) + } + + pub fn overwrite_cpu_pixels_from_gpu( + &self, + mc: &Mutation<'gc>, + ) -> (GcCell<'gc, BitmapRawData<'gc>>, Option) { + self.0.overwrite_cpu_pixels_from_gpu(mc) + } + + pub fn read_area( + &self, + read_area: PixelRegion, + renderer: &mut dyn RenderBackend, + ) -> Ref<'_, BitmapRawData<'gc>> { + self.0.read_area(read_area, renderer) + } + + pub fn height(&self) -> u32 { + self.0.height() + } + + pub fn width(&self) -> u32 { + self.0.width() + } + + pub fn object2(&self) -> Avm2Value<'gc> { + self.0.object2() + } + + pub fn disposed(&self) -> bool { + self.0.disposed() + } + + pub fn transparency(&self) -> bool { + self.0.transparency() + } + + pub fn check_valid( + &self, + activation: &mut crate::avm2::Activation<'_, 'gc>, + ) -> Result<(), crate::avm2::Error<'gc>> { + self.0.check_valid(activation) + } + + pub fn dispose(&self, mc: &Mutation<'gc>) { + self.0.dispose(mc); + } + + pub fn init_object2(&self, mc: &Mutation<'gc>, object: Avm2Object<'gc>) { + self.0.init_object2(mc, object); + } + + pub fn remove_display_object(&self, mc: &Mutation<'gc>, callback: DisplayObjectWeak<'gc>) { + self.0.remove_display_object(mc, callback); + } + + pub fn add_display_object(&self, mc: &Mutation<'gc>, callback: DisplayObjectWeak<'gc>) { + self.0.add_display_object(mc, callback); + } + + pub fn render( + &self, + smoothing: bool, + context: &mut RenderContext<'_, 'gc>, + pixel_snapping: PixelSnapping, + ) { + self.0.render(smoothing, context, pixel_snapping); + } + + pub fn can_read(&self, read_area: PixelRegion) -> bool { + self.0.can_read(read_area) + } + + #[cfg(feature = "egui")] + pub fn debug_sync_status(&self) -> std::borrow::Cow<'static, str> { + self.0.debug_sync_status() + } + + pub fn is_point_in_bounds(&self, x: i32, y: i32) -> bool { + self.0.is_point_in_bounds(x, y) + } + + pub fn ptr_eq(&self, other: BitmapData<'gc>) -> bool { + self.0.ptr_eq(other.0) + } +} + #[derive(Collect)] #[collect(no_drop)] -pub struct BitmapData<'gc> { +pub struct BitmapRawData<'gc> { /// The pixels in the bitmap, stored as a array of pre-multiplied ARGB colour values #[collect(require_static)] pixels: Vec, @@ -242,7 +388,7 @@ enum DirtyState { // The CPU pixels have been modified, and need to be synced to the GPU via `update_dirty_texture` CpuModified(PixelRegion), - // The GPU pixels have been modified, and need to be synced to the CPU via `BitmapDataWrapper::sync` + // The GPU pixels have been modified, and need to be synced to the CPU via `BitmapRawDataWrapper::sync` GpuModified(Box, PixelRegion), } @@ -256,7 +402,7 @@ mod wrapper { use ruffle_render::commands::CommandHandler; use std::cell::Ref; - use super::{copy_pixels_to_bitmapdata, BitmapData, DirtyState}; + use super::{copy_pixels_to_bitmapdata, BitmapRawData, DirtyState}; /// A wrapper type that ensures that we always wait for a pending /// GPU -> CPU sync to complete (using `sync_handle`) before accessing @@ -288,11 +434,11 @@ mod wrapper { /// `sync_handle` and `dirty` can never be set at the same time - we can only have one of them set, or none of them set. #[derive(Copy, Clone, Collect, Debug)] #[collect(no_drop)] - pub struct BitmapDataWrapper<'gc>(GcCell<'gc, BitmapData<'gc>>); + pub struct BitmapRawDataWrapper<'gc>(GcCell<'gc, BitmapRawData<'gc>>); - impl<'gc> BitmapDataWrapper<'gc> { - pub fn new(data: GcCell<'gc, BitmapData<'gc>>) -> Self { - BitmapDataWrapper(data) + impl<'gc> BitmapRawDataWrapper<'gc> { + pub fn new(data: GcCell<'gc, BitmapRawData<'gc>>) -> Self { + BitmapRawDataWrapper(data) } // Creates a dummy BitmapData with no pixels or handle, marked as disposed. @@ -300,9 +446,9 @@ mod wrapper { // Marking it as disposed skips rendering, and the unset `avm2_object` will cause this to // be inaccessible to AS3 code. pub fn dummy(mc: &Mutation<'gc>) -> Self { - BitmapDataWrapper(GcCell::new( + BitmapRawDataWrapper(GcCell::new( mc, - BitmapData { + BitmapRawData { pixels: Vec::new(), width: 0, height: 0, @@ -320,12 +466,12 @@ mod wrapper { /// Clones the underlying data, producing a new `BitmapData` /// that has no GPU texture or associated display objects - pub fn clone_data(&self, renderer: &mut dyn RenderBackend) -> BitmapData<'gc> { + pub fn clone_data(&self, renderer: &mut dyn RenderBackend) -> BitmapRawData<'gc> { // Sync from the GPU to CPU, since our new BitmapData starts out // with no GPU texture let data = self.sync(renderer); let data = data.read(); - BitmapData { + BitmapRawData { pixels: data.pixels.clone(), width: data.width, height: data.height, @@ -343,7 +489,7 @@ mod wrapper { // Provides access to the underlying `BitmapData`. If a GPU -> CPU sync // is in progress, waits for it to complete - pub fn sync(&self, renderer: &mut dyn RenderBackend) -> GcCell<'gc, BitmapData<'gc>> { + pub fn sync(&self, renderer: &mut dyn RenderBackend) -> GcCell<'gc, BitmapRawData<'gc>> { // SAFETY: The only fields that can store gc pointers are `avm2_object` and `dirty_callbacks`, // which we don't update here. Ideally, we would refactor this so that // `BitmapData` doesn't contain any gc pointers, allowing us to use a normal @@ -392,7 +538,7 @@ mod wrapper { pub fn overwrite_cpu_pixels_from_gpu( &self, mc: &Mutation<'gc>, - ) -> (GcCell<'gc, BitmapData<'gc>>, Option) { + ) -> (GcCell<'gc, BitmapRawData<'gc>>, Option) { let mut write = self.0.write(mc); let dirty_rect = match write.dirty_state { DirtyState::GpuModified(_, rect) => { @@ -413,7 +559,7 @@ mod wrapper { &self, read_area: PixelRegion, renderer: &mut dyn RenderBackend, - ) -> Ref<'_, BitmapData<'gc>> { + ) -> Ref<'_, BitmapRawData<'gc>> { let needs_update = if let DirtyState::GpuModified(_, area) = self.0.read().dirty_state { area.intersects(read_area) } else { @@ -426,7 +572,7 @@ mod wrapper { } // These methods do not require a sync to complete, as they do not depend on the - // CPU-side pixels. They are implemented directly on `BitmapDataWrapper`, allowing + // CPU-side pixels. They are implemented directly on `BitmapRawDataWrapper`, allowing // callers to avoid calling sync() pub fn height(&self) -> u32 { @@ -539,17 +685,17 @@ mod wrapper { x >= 0 && x < self.width() as i32 && y >= 0 && y < self.height() as i32 } - pub fn ptr_eq(&self, other: BitmapDataWrapper<'gc>) -> bool { + pub fn ptr_eq(&self, other: BitmapRawDataWrapper<'gc>) -> bool { GcCell::ptr_eq(self.0, other.0) } } } -pub use wrapper::BitmapDataWrapper; +pub use wrapper::BitmapRawDataWrapper; -impl std::fmt::Debug for BitmapData<'_> { +impl std::fmt::Debug for BitmapRawData<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("BitmapData") + f.debug_struct("BitmapRawData") .field("dirty_state", &self.dirty_state) .field("width", &self.width) .field("height", &self.height) @@ -560,7 +706,7 @@ impl std::fmt::Debug for BitmapData<'_> { } } -impl<'gc> BitmapData<'gc> { +impl<'gc> BitmapRawData<'gc> { pub fn new(width: u32, height: u32, transparency: bool, fill_color: u32) -> Self { Self { pixels: vec![ @@ -625,7 +771,7 @@ impl<'gc> BitmapData<'gc> { ); let bitmap_handle = renderer.register_bitmap(bitmap); if let Err(e) = &bitmap_handle { - tracing::warn!("Failed to register raw bitmap for BitmapData: {:?}", e); + tracing::warn!("Failed to register raw bitmap for BitmapRawData: {:?}", e); } self.bitmap_handle = bitmap_handle.ok(); } @@ -736,7 +882,7 @@ impl<'gc> BitmapData<'gc> { &self.pixels } - // Updates the data stored with our `BitmapHandle` if this `BitmapData` + // Updates the data stored with our `BitmapHandle` if this `BitmapRawData` // is dirty pub fn update_dirty_texture(&mut self, renderer: &mut dyn RenderBackend) { let handle = self.bitmap_handle(renderer).unwrap(); @@ -780,7 +926,7 @@ impl<'gc> BitmapData<'gc> { } pub enum IBitmapDrawable<'gc> { - BitmapData(BitmapDataWrapper<'gc>), + BitmapData(BitmapData<'gc>), DisplayObject(DisplayObject<'gc>), } @@ -800,7 +946,7 @@ impl IBitmapDrawable<'_> { #[instrument(level = "debug", skip_all)] fn copy_pixels_to_bitmapdata( - write: &mut BitmapData, + write: &mut BitmapRawData, buffer: &[u8], buffer_width: u32, area: PixelRegion, diff --git a/core/src/bitmap/operations.rs b/core/src/bitmap/operations.rs index c309597c18ca..54bee4f3289b 100644 --- a/core/src/bitmap/operations.rs +++ b/core/src/bitmap/operations.rs @@ -3,7 +3,7 @@ use crate::avm2::error::make_error_2006; use crate::avm2::vector::VectorStorage; use crate::avm2::{Activation, Error, Value as Avm2Value}; use crate::bitmap::bitmap_data::{ - BitmapData, BitmapDataDrawError, BitmapDataWrapper, ChannelOptions, Color, IBitmapDrawable, + BitmapData, BitmapDataDrawError, BitmapRawData, ChannelOptions, Color, IBitmapDrawable, LehmerRng, ThresholdOperation, }; use crate::bitmap::turbulence::Turbulence; @@ -30,7 +30,7 @@ use swf::{BlendMode, ColorTransform, Fixed8, Rectangle, Twips}; pub fn fill_rect<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, x: i32, y: i32, width: i32, @@ -69,7 +69,7 @@ pub fn fill_rect<'gc>( pub fn set_pixel32<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, x: u32, y: u32, color: u32, @@ -88,12 +88,7 @@ pub fn set_pixel32<'gc>( write.set_cpu_dirty(mc, PixelRegion::for_pixel(x, y)); } -pub fn get_pixel32( - target: BitmapDataWrapper, - renderer: &mut dyn RenderBackend, - x: u32, - y: u32, -) -> u32 { +pub fn get_pixel32(target: BitmapData, renderer: &mut dyn RenderBackend, x: u32, y: u32) -> u32 { if x >= target.width() || y >= target.height() { return 0; } @@ -104,7 +99,7 @@ pub fn get_pixel32( pub fn set_pixel<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, x: u32, y: u32, color: Color, @@ -125,12 +120,7 @@ pub fn set_pixel<'gc>( write.set_cpu_dirty(mc, PixelRegion::for_pixel(x, y)); } -pub fn get_pixel( - target: BitmapDataWrapper, - renderer: &mut dyn RenderBackend, - x: u32, - y: u32, -) -> u32 { +pub fn get_pixel(target: BitmapData, renderer: &mut dyn RenderBackend, x: u32, y: u32) -> u32 { if x >= target.width() || y >= target.height() { return 0; } @@ -143,7 +133,7 @@ pub fn get_pixel( pub fn flood_fill<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, x: u32, y: u32, color: u32, @@ -190,7 +180,7 @@ pub fn flood_fill<'gc>( pub fn noise<'gc>( mc: &Mutation<'gc>, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, seed: i32, low: u8, high: u8, @@ -257,7 +247,7 @@ pub fn noise<'gc>( #[allow(clippy::too_many_arguments)] pub fn perlin_noise<'gc>( mc: &Mutation<'gc>, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, base: (f64, f64), num_octaves: usize, random_seed: i64, @@ -375,10 +365,10 @@ pub fn perlin_noise<'gc>( pub fn copy_channel<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, dest_point: (i32, i32), src_rect: (i32, i32, i32, i32), - source_bitmap: BitmapDataWrapper<'gc>, + source_bitmap: BitmapData<'gc>, source_channel: i32, dest_channel: i32, ) { @@ -466,7 +456,7 @@ pub fn copy_channel<'gc>( pub fn color_transform<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, x_min: u32, y_min: u32, x_max: u32, @@ -520,8 +510,8 @@ pub fn color_transform<'gc>( pub fn threshold<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, - source_bitmap: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, + source_bitmap: BitmapData<'gc>, src_rect: (i32, i32, i32, i32), dest_point: (i32, i32), operation: ThresholdOperation, @@ -620,7 +610,7 @@ pub fn threshold<'gc>( pub fn scroll<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, x: i32, y: i32, ) { @@ -674,8 +664,8 @@ pub fn scroll<'gc>( pub fn palette_map<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, - source_bitmap: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, + source_bitmap: BitmapData<'gc>, src_rect: (i32, i32, i32, i32), dest_point: (i32, i32), channel_arrays: ([u32; 256], [u32; 256], [u32; 256], [u32; 256]), @@ -739,9 +729,10 @@ pub fn palette_map<'gc>( /// Compare two BitmapData objects. /// Returns `None` if the bitmaps are equivalent. pub fn compare<'gc>( + mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - left: BitmapDataWrapper<'gc>, - right: BitmapDataWrapper<'gc>, + left: BitmapData<'gc>, + right: BitmapData<'gc>, ) -> Option> { // This function expects that the two bitmaps have the same dimensions. // TODO: Relax this assumption and return a special value instead? @@ -781,6 +772,7 @@ pub fn compare<'gc>( if different { Some(BitmapData::new_with_pixels( + mc, left.width(), left.height(), true, @@ -793,7 +785,7 @@ pub fn compare<'gc>( pub fn hit_test_point( renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper, + target: BitmapData, alpha_threshold: u8, test_point: (i32, i32), ) -> bool { @@ -812,7 +804,7 @@ pub fn hit_test_point( pub fn hit_test_rectangle( renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper, + target: BitmapData, alpha_threshold: u8, top_left: (i32, i32), size: (i32, i32), @@ -833,10 +825,10 @@ pub fn hit_test_rectangle( pub fn hit_test_bitmapdata<'gc>( renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, self_point: (i32, i32), self_threshold: u8, - test: BitmapDataWrapper<'gc>, + test: BitmapData<'gc>, test_point: (i32, i32), test_threshold: u8, ) -> bool { @@ -894,7 +886,7 @@ pub fn hit_test_bitmapdata<'gc>( pub fn color_bounds_rect( renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper, + target: BitmapData, find_color: bool, mask: u32, color: u32, @@ -940,8 +932,8 @@ pub fn color_bounds_rect( pub fn merge<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, - source_bitmap: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, + source_bitmap: BitmapData<'gc>, src_rect: (i32, i32, i32, i32), dest_point: (i32, i32), rgba_mult: (i32, i32, i32, i32), @@ -1025,8 +1017,8 @@ pub fn merge<'gc>( pub fn copy_pixels<'gc>( context: &mut UpdateContext<'gc>, - target: BitmapDataWrapper<'gc>, - source_bitmap: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, + source_bitmap: BitmapData<'gc>, src_rect: (i32, i32, i32, i32), dest_point: (i32, i32), merge_alpha: bool, @@ -1064,11 +1056,11 @@ pub fn copy_pixels<'gc>( #[allow(clippy::too_many_arguments)] pub fn copy_pixels_with_alpha_source<'gc>( context: &mut UpdateContext<'gc>, - target: BitmapDataWrapper<'gc>, - source_bitmap: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, + source_bitmap: BitmapData<'gc>, src_rect: (i32, i32, i32, i32), dest_point: (i32, i32), - alpha_bitmap: BitmapDataWrapper<'gc>, + alpha_bitmap: BitmapData<'gc>, alpha_point: (i32, i32), merge_alpha: bool, ) { @@ -1202,8 +1194,8 @@ pub fn copy_pixels_with_alpha_source<'gc>( pub fn apply_filter<'gc>( context: &mut UpdateContext<'gc>, - target: BitmapDataWrapper<'gc>, - source: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, + source: BitmapData<'gc>, source_point: (u32, u32), source_size: (u32, u32), dest_point: (u32, u32), @@ -1273,8 +1265,8 @@ pub fn apply_filter<'gc>( fn copy_on_cpu<'gc>( context: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - source: BitmapDataWrapper<'gc>, - dest: BitmapDataWrapper<'gc>, + source: BitmapData<'gc>, + dest: BitmapData<'gc>, source_region: PixelRegion, dest_region: PixelRegion, mut blend: bool, @@ -1369,8 +1361,8 @@ fn copy_on_cpu<'gc>( #[allow(clippy::too_many_arguments)] fn blend_and_transform<'gc>( context: &mut UpdateContext<'gc>, - source: BitmapDataWrapper<'gc>, - dest: BitmapDataWrapper<'gc>, + source: BitmapData<'gc>, + dest: BitmapData<'gc>, source_region: PixelRegion, dest_region: PixelRegion, transform: &ColorTransform, @@ -1425,7 +1417,7 @@ fn blend_and_transform<'gc>( #[allow(clippy::too_many_arguments)] pub fn draw<'gc>( context: &mut UpdateContext<'gc>, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, mut source: IBitmapDrawable<'gc>, transform: Transform, smoothing: bool, @@ -1615,7 +1607,7 @@ pub fn draw<'gc>( } pub fn get_vector<'gc>( - target: BitmapDataWrapper, + target: BitmapData, renderer: &mut dyn RenderBackend, x: i32, y: i32, @@ -1642,7 +1634,7 @@ pub fn get_vector<'gc>( pub fn set_vector<'gc>( activation: &mut Activation<'_, 'gc>, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, x_min: u32, y_min: u32, x_max: u32, @@ -1682,7 +1674,7 @@ pub fn set_vector<'gc>( pub fn get_pixels_as_byte_array<'gc>( activation: &mut Activation<'_, 'gc>, - target: BitmapDataWrapper, + target: BitmapData, x: i32, y: i32, width: i32, @@ -1709,7 +1701,7 @@ pub fn get_pixels_as_byte_array<'gc>( pub fn set_pixels_from_byte_array<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, x: i32, y: i32, width: i32, @@ -1752,8 +1744,8 @@ pub fn set_pixels_from_byte_array<'gc>( pub fn pixel_dissolve<'gc>( mc: &Mutation<'gc>, renderer: &mut dyn RenderBackend, - target: BitmapDataWrapper<'gc>, - source_bitmap: BitmapDataWrapper<'gc>, + target: BitmapData<'gc>, + source_bitmap: BitmapData<'gc>, src_rect: (i32, i32, i32, i32), dest_point: (i32, i32), random_seed: i32, @@ -1826,8 +1818,8 @@ pub fn pixel_dissolve<'gc>( } fn write_pixel( - write: &mut RefMut, - different_source_than_target: &Option>, + write: &mut RefMut, + different_source_than_target: &Option>, fill_color: u32, transparency: bool, base_point: (u32, u32), diff --git a/core/src/debug_ui/display_object.rs b/core/src/debug_ui/display_object.rs index d4f36321271b..4a7f09bde0c1 100644 --- a/core/src/debug_ui/display_object.rs +++ b/core/src/debug_ui/display_object.rs @@ -654,7 +654,8 @@ impl DisplayObjectWindow { context: &mut UpdateContext<'gc>, object: Bitmap<'gc>, ) { - let bitmap_data = object.bitmap_data(context.renderer); + let bitmap_data = object.bitmap_data(); + let bitmap_data = bitmap_data.sync(context.renderer); let bitmap_data = bitmap_data.read(); let mut egui_texture = bitmap_data.egui_texture.borrow_mut(); let texture = egui_texture.get_or_insert_with(|| { diff --git a/core/src/display_object/bitmap.rs b/core/src/display_object/bitmap.rs index b0b727f8fdcc..f6618d93f3f7 100644 --- a/core/src/display_object/bitmap.rs +++ b/core/src/display_object/bitmap.rs @@ -6,7 +6,7 @@ use crate::avm2::{ ClassObject as Avm2ClassObject, Object as Avm2Object, StageObject as Avm2StageObject, TObject, Value as Avm2Value, }; -use crate::bitmap::bitmap_data::{BitmapData, BitmapDataWrapper}; +use crate::bitmap::bitmap_data::BitmapData; use crate::context::{RenderContext, UpdateContext}; use crate::display_object::{DisplayObjectBase, DisplayObjectPtr, DisplayObjectWeak}; use crate::prelude::*; @@ -14,7 +14,6 @@ use crate::tag_utils::SwfMovie; use crate::vminterface::Instantiator; use core::fmt; use gc_arena::{Collect, GcCell, GcWeakCell, Mutation}; -use ruffle_render::backend::RenderBackend; use ruffle_render::bitmap::{BitmapFormat, PixelSnapping}; use std::cell::{Ref, RefMut}; use std::sync::Arc; @@ -102,9 +101,9 @@ pub struct BitmapGraphicData<'gc> { movie: Arc, /// The current bitmap data object. - bitmap_data: BitmapDataWrapper<'gc>, + bitmap_data: BitmapData<'gc>, - /// The width and height values are cached from the BitmapDataWrapper + /// The width and height values are cached from the BitmapData /// when this Bitmap instance is first created, /// and continue to be reported even if the BitmapData is disposed. width: u32, @@ -138,7 +137,7 @@ impl<'gc> Bitmap<'gc> { pub fn new_with_bitmap_data( mc: &Mutation<'gc>, id: CharacterId, - bitmap_data: BitmapDataWrapper<'gc>, + bitmap_data: BitmapData<'gc>, smoothing: bool, movie: &Arc, ) -> Self { @@ -189,13 +188,13 @@ impl<'gc> Bitmap<'gc> { .as_colors() .map(crate::bitmap::bitmap_data::Color::from) .collect(); - let bitmap_data = BitmapData::new_with_pixels(width, height, transparency, pixels); + let bitmap_data = BitmapData::new_with_pixels(mc, width, height, transparency, pixels); let smoothing = true; Ok(Self::new_with_bitmap_data( mc, id, - BitmapDataWrapper::new(GcCell::new(mc, bitmap_data)), + bitmap_data, smoothing, &movie, )) @@ -220,15 +219,10 @@ impl<'gc> Bitmap<'gc> { self.0.write(mc).pixel_snapping = value; } - pub fn bitmap_data_wrapper(self) -> BitmapDataWrapper<'gc> { + pub fn bitmap_data(self) -> BitmapData<'gc> { self.0.read().bitmap_data } - /// Retrieve the bitmap data associated with this `Bitmap`. - pub fn bitmap_data(self, renderer: &mut dyn RenderBackend) -> GcCell<'gc, BitmapData<'gc>> { - self.0.read().bitmap_data.sync(renderer) - } - /// Associate this `Bitmap` with new `BitmapData`. /// /// Once associated with the new data, the reported width, height, and @@ -237,11 +231,7 @@ impl<'gc> Bitmap<'gc> { /// /// This also forces the `BitmapData` to be sent to the rendering backend, /// if that has not already been done. - pub fn set_bitmap_data( - self, - context: &mut UpdateContext<'gc>, - bitmap_data: BitmapDataWrapper<'gc>, - ) { + pub fn set_bitmap_data(self, context: &mut UpdateContext<'gc>, bitmap_data: BitmapData<'gc>) { let weak_self = DisplayObjectWeak::Bitmap(self.downgrade()); let mut write = self.0.write(context.gc_context); @@ -352,7 +342,7 @@ impl<'gc> TDisplayObject<'gc> for Bitmap<'gc> { // even if it's linked to an image. let bitmap_data_obj = Avm2BitmapDataObject::from_bitmap_data_internal( &mut activation, - BitmapDataWrapper::dummy(mc), + BitmapData::dummy(mc), bitmapdata_cls, ) .expect("can't throw from post_instantiation -_-"); diff --git a/core/src/loader.rs b/core/src/loader.rs index adab15cde280..642c0c910a82 100644 --- a/core/src/loader.rs +++ b/core/src/loader.rs @@ -16,8 +16,8 @@ use crate::avm2::{ }; use crate::backend::navigator::{ErrorResponse, OwnedFuture, Request, SuccessResponse}; use crate::backend::ui::DialogResultFuture; +use crate::bitmap::bitmap_data::BitmapData; use crate::bitmap::bitmap_data::Color; -use crate::bitmap::bitmap_data::{BitmapData, BitmapDataWrapper}; use crate::context::{ActionQueue, ActionType, UpdateContext}; use crate::display_object::{ DisplayObject, MovieClip, TDisplayObject, TDisplayObjectContainer, TInteractiveObject, @@ -33,7 +33,7 @@ use crate::vminterface::Instantiator; use crate::{avm2_stub_method, avm2_stub_method_context}; use chardetng::EncodingDetector; use encoding_rs::{UTF_8, WINDOWS_1252}; -use gc_arena::{Collect, GcCell}; +use gc_arena::Collect; use indexmap::IndexMap; use ruffle_render::utils::{determine_jpeg_tag_format, JpegTagFormat}; use slotmap::{new_key_type, SlotMap}; @@ -2222,18 +2222,17 @@ impl<'gc> Loader<'gc> { let bitmap = ruffle_render::utils::decode_define_bits_jpeg(data, None)?; let transparency = true; - let bitmap_data = BitmapData::new_with_pixels( + let bitmapdata = BitmapData::new_with_pixels( + activation.context.gc_context, bitmap.width(), bitmap.height(), transparency, bitmap.as_colors().map(Color::from).collect(), ); - let bitmapdata_wrapper = - BitmapDataWrapper::new(GcCell::new(activation.context.gc_context, bitmap_data)); let bitmapdata_class = activation.context.avm2.classes().bitmapdata; let bitmapdata_avm2 = BitmapDataObject::from_bitmap_data_internal( &mut activation, - bitmapdata_wrapper, + bitmapdata, bitmapdata_class, ) .unwrap();