diff --git a/core/src/display_object.rs b/core/src/display_object.rs index 83bc8b4d4ffa..75dc94c54287 100644 --- a/core/src/display_object.rs +++ b/core/src/display_object.rs @@ -2237,7 +2237,7 @@ pub trait TDisplayObject<'gc>: } } if let Some(ratio) = place_object.ratio { - if let Some(mut morph_shape) = self.as_morph_shape() { + if let Some(morph_shape) = self.as_morph_shape() { morph_shape.set_ratio(context.gc(), ratio); } else if let Some(video) = self.as_video() { video.seek(context, ratio.into()); diff --git a/core/src/display_object/loader_display.rs b/core/src/display_object/loader_display.rs index d0034e2b96fd..944fbfa6310a 100644 --- a/core/src/display_object/loader_display.rs +++ b/core/src/display_object/loader_display.rs @@ -12,8 +12,9 @@ use crate::display_object::container::ChildContainer; use crate::display_object::interactive::InteractiveObjectBase; use crate::tag_utils::SwfMovie; use core::fmt; -use gc_arena::GcWeakCell; -use gc_arena::{Collect, GcCell, Mutation}; +use gc_arena::barrier::unlock; +use gc_arena::lock::{Lock, RefLock}; +use gc_arena::{Collect, Gc, GcWeak, Mutation}; use std::cell::{Ref, RefMut}; use std::sync::Arc; @@ -21,12 +22,12 @@ use super::interactive::Avm2MousePick; #[derive(Clone, Collect, Copy)] #[collect(no_drop)] -pub struct LoaderDisplay<'gc>(GcCell<'gc, LoaderDisplayData<'gc>>); +pub struct LoaderDisplay<'gc>(Gc<'gc, LoaderDisplayData<'gc>>); impl fmt::Debug for LoaderDisplay<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("LoaderDisplay") - .field("ptr", &self.0.as_ptr()) + .field("ptr", &Gc::as_ptr(self.0)) .finish() } } @@ -34,20 +35,20 @@ impl fmt::Debug for LoaderDisplay<'_> { #[derive(Clone, Collect)] #[collect(no_drop)] pub struct LoaderDisplayData<'gc> { - base: InteractiveObjectBase<'gc>, - container: ChildContainer<'gc>, - avm2_object: Option>, + base: RefLock>, + container: RefLock>, + avm2_object: Lock>>, movie: Arc, } impl<'gc> LoaderDisplay<'gc> { pub fn empty(activation: &mut Activation<'_, 'gc>, movie: Arc) -> Self { - let obj = LoaderDisplay(GcCell::new( + let obj = LoaderDisplay(Gc::new( activation.gc(), LoaderDisplayData { - base: Default::default(), - container: ChildContainer::new(movie.clone()), - avm2_object: None, + base: RefLock::new(Default::default()), + container: RefLock::new(ChildContainer::new(movie.clone())), + avm2_object: Lock::new(None), movie, }, )); @@ -58,25 +59,25 @@ impl<'gc> LoaderDisplay<'gc> { } pub fn downgrade(self) -> LoaderDisplayWeak<'gc> { - LoaderDisplayWeak(GcCell::downgrade(self.0)) + LoaderDisplayWeak(Gc::downgrade(self.0)) } } impl<'gc> TDisplayObject<'gc> for LoaderDisplay<'gc> { fn base(&self) -> Ref> { - Ref::map(self.0.read(), |r| &r.base.base) + Ref::map(self.raw_interactive(), |r| &r.base) } fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> { - RefMut::map(self.0.write(mc), |w| &mut w.base.base) + RefMut::map(self.raw_interactive_mut(mc), |w| &mut w.base) } fn instantiate(&self, gc_context: &Mutation<'gc>) -> DisplayObject<'gc> { - Self(GcCell::new(gc_context, self.0.read().clone())).into() + Self(Gc::new(gc_context, self.0.as_ref().clone())).into() } fn as_ptr(&self) -> *const DisplayObjectPtr { - self.0.as_ptr() as *const DisplayObjectPtr + Gc::as_ptr(self.0) as *const DisplayObjectPtr } fn id(&self) -> CharacterId { @@ -93,14 +94,15 @@ impl<'gc> TDisplayObject<'gc> for LoaderDisplay<'gc> { fn object2(&self) -> Avm2Value<'gc> { self.0 - .read() .avm2_object + .get() .map(Avm2Value::from) .unwrap_or(Avm2Value::Null) } fn set_object2(&self, context: &mut UpdateContext<'gc>, to: Avm2Object<'gc>) { - self.0.write(context.gc()).avm2_object = Some(to); + let mc = context.gc(); + unlock!(Gc::write(mc, self.0), LoaderDisplayData, avm2_object).set(Some(to)) } fn as_container(self) -> Option> { @@ -130,7 +132,7 @@ impl<'gc> TDisplayObject<'gc> for LoaderDisplay<'gc> { } fn movie(&self) -> Arc { - self.0.read().movie.clone() + self.0.movie.clone() } fn on_parent_removed(&self, context: &mut UpdateContext<'gc>) { @@ -142,11 +144,11 @@ impl<'gc> TDisplayObject<'gc> for LoaderDisplay<'gc> { impl<'gc> TInteractiveObject<'gc> for LoaderDisplay<'gc> { fn raw_interactive(&self) -> Ref> { - Ref::map(self.0.read(), |r| &r.base) + self.0.base.borrow() } fn raw_interactive_mut(&self, mc: &Mutation<'gc>) -> RefMut> { - RefMut::map(self.0.write(mc), |w| &mut w.base) + unlock!(Gc::write(mc, self.0), LoaderDisplayData, base).borrow_mut() } fn as_displayobject(self) -> DisplayObject<'gc> { @@ -254,17 +256,17 @@ impl<'gc> TInteractiveObject<'gc> for LoaderDisplay<'gc> { impl<'gc> TDisplayObjectContainer<'gc> for LoaderDisplay<'gc> { fn raw_container(&self) -> Ref<'_, ChildContainer<'gc>> { - Ref::map(self.0.read(), |this| &this.container) + self.0.container.borrow() } fn raw_container_mut(&self, gc_context: &Mutation<'gc>) -> RefMut<'_, ChildContainer<'gc>> { - RefMut::map(self.0.write(gc_context), |this| &mut this.container) + unlock!(Gc::write(gc_context, self.0), LoaderDisplayData, container).borrow_mut() } } #[derive(Clone, Debug, Collect, Copy)] #[collect(no_drop)] -pub struct LoaderDisplayWeak<'gc>(GcWeakCell<'gc, LoaderDisplayData<'gc>>); +pub struct LoaderDisplayWeak<'gc>(GcWeak<'gc, LoaderDisplayData<'gc>>); impl<'gc> LoaderDisplayWeak<'gc> { pub fn upgrade(self, mc: &Mutation<'gc>) -> Option> { diff --git a/core/src/display_object/morph_shape.rs b/core/src/display_object/morph_shape.rs index 033220129203..548b50d14ca1 100644 --- a/core/src/display_object/morph_shape.rs +++ b/core/src/display_object/morph_shape.rs @@ -7,21 +7,23 @@ use crate::library::{Library, MovieLibrarySource}; use crate::prelude::*; use crate::tag_utils::SwfMovie; use core::fmt; -use gc_arena::{Collect, Gc, GcCell, Mutation}; +use gc_arena::barrier::unlock; +use gc_arena::lock::{Lock, RefLock}; +use gc_arena::{Collect, Gc, Mutation}; use ruffle_render::backend::ShapeHandle; use ruffle_render::commands::CommandHandler; -use std::cell::{Ref, RefCell, RefMut}; +use std::cell::{Cell, Ref, RefCell, RefMut}; use std::sync::Arc; use swf::{Fixed16, Fixed8}; #[derive(Clone, Collect, Copy)] #[collect(no_drop)] -pub struct MorphShape<'gc>(GcCell<'gc, MorphShapeData<'gc>>); +pub struct MorphShape<'gc>(Gc<'gc, MorphShapeData<'gc>>); impl fmt::Debug for MorphShape<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MorphShape") - .field("ptr", &self.0.as_ptr()) + .field("ptr", &Gc::as_ptr(self.0)) .finish() } } @@ -29,11 +31,11 @@ impl fmt::Debug for MorphShape<'_> { #[derive(Clone, Collect)] #[collect(no_drop)] pub struct MorphShapeData<'gc> { - base: DisplayObjectBase<'gc>, - shared: Gc<'gc, MorphShapeShared>, - ratio: u16, + base: RefLock>, + shared: Lock>, + ratio: Cell, /// The AVM2 representation of this MorphShape. - object: Option>, + object: Lock>>, } impl<'gc> MorphShape<'gc> { @@ -43,46 +45,46 @@ impl<'gc> MorphShape<'gc> { movie: Arc, ) -> Self { let shared = MorphShapeShared::from_swf_tag(&tag, movie); - MorphShape(GcCell::new( + MorphShape(Gc::new( gc_context, MorphShapeData { base: Default::default(), - shared: Gc::new(gc_context, shared), - ratio: 0, - object: None, + shared: Lock::new(Gc::new(gc_context, shared)), + ratio: Cell::new(0), + object: Lock::new(None), }, )) } pub fn ratio(self) -> u16 { - self.0.read().ratio + self.0.ratio.get() } - pub fn set_ratio(&mut self, gc_context: &Mutation<'gc>, ratio: u16) { - self.0.write(gc_context).ratio = ratio; + pub fn set_ratio(self, gc_context: &Mutation<'gc>, ratio: u16) { + self.0.ratio.set(ratio); self.invalidate_cached_bitmap(gc_context); } } impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> { fn base(&self) -> Ref> { - Ref::map(self.0.read(), |r| &r.base) + self.0.base.borrow() } fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> { - RefMut::map(self.0.write(mc), |w| &mut w.base) + unlock!(Gc::write(mc, self.0), MorphShapeData, base).borrow_mut() } fn instantiate(&self, gc_context: &Mutation<'gc>) -> DisplayObject<'gc> { - Self(GcCell::new(gc_context, self.0.read().clone())).into() + Self(Gc::new(gc_context, self.0.as_ref().clone())).into() } fn as_ptr(&self) -> *const DisplayObjectPtr { - self.0.as_ptr() as *const DisplayObjectPtr + Gc::as_ptr(self.0) as *const DisplayObjectPtr } fn id(&self) -> CharacterId { - self.0.read().shared.id + self.0.shared.get().id } fn as_morph_shape(&self) -> Option { @@ -95,7 +97,8 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> { .library_for_movie_mut(self.movie()) .get_morph_shape(id) { - self.0.write(context.gc()).shared = new_morph_shape.0.read().shared; + unlock!(Gc::write(context.gc(), self.0), MorphShapeData, shared) + .set(new_morph_shape.0.shared.get()) } else { tracing::warn!("PlaceObject: expected morph shape at character ID {}", id); } @@ -108,14 +111,15 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> { fn object2(&self) -> Avm2Value<'gc> { self.0 - .read() .object + .get() .map(Avm2Value::from) .unwrap_or(Avm2Value::Null) } fn set_object2(&self, context: &mut UpdateContext<'gc>, to: Avm2Object<'gc>) { - self.0.write(context.gc()).object = Some(to); + let mc = context.gc(); + unlock!(Gc::write(mc, self.0), MorphShapeData, object).set(Some(to)) } /// Construct objects placed on this frame. @@ -128,7 +132,7 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> { (*self).into(), class, ) { - Ok(object) => self.0.write(context.gc()).object = Some(object.into()), + Ok(object) => self.set_object2(context, object.into()), Err(e) => tracing::error!("Got {} when constructing AVM2 side of MorphShape", e), }; self.on_construction_complete(context); @@ -136,9 +140,8 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> { } fn render_self(&self, context: &mut RenderContext) { - let this = self.0.read(); - let ratio = this.ratio; - let shared = this.shared; + let ratio = self.0.ratio.get(); + let shared = self.0.shared.get(); let shape_handle = shared.get_shape(context, context.library, ratio); context .commands @@ -146,9 +149,8 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> { } fn self_bounds(&self) -> Rectangle { - let this = self.0.read(); - let ratio = this.ratio; - let shared = this.shared; + let ratio = self.0.ratio.get(); + let shared = self.0.shared.get(); let frame = shared.get_frame(ratio); frame.bounds.clone() } @@ -162,7 +164,7 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> { if (!options.contains(HitTestOptions::SKIP_INVISIBLE) || self.visible()) && self.world_bounds().contains(point) { - if let Some(frame) = self.0.read().shared.frames.borrow().get(&self.ratio()) { + if let Some(frame) = self.0.shared.get().frames.borrow().get(&self.ratio()) { let Some(local_matrix) = self.global_to_local_matrix() else { return false; }; @@ -180,7 +182,7 @@ impl<'gc> TDisplayObject<'gc> for MorphShape<'gc> { } fn movie(&self) -> Arc { - self.0.read().shared.movie.clone() + self.0.shared.get().movie.clone() } }