Skip to content

Commit bf9c4c3

Browse files
kjaroshLord-McSweeney
authored andcommitted
core: Replace GcCell with Gc in Bitmap
This refactor replaces GcCell with Gc and uses interior mutability instead.
1 parent e433e01 commit bf9c4c3

File tree

2 files changed

+70
-59
lines changed

2 files changed

+70
-59
lines changed

core/src/avm2/globals/flash/display/bitmap.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ pub fn init<'gc>(
110110
if let Some(bitmap_data) = bitmap_data {
111111
bitmap.set_bitmap_data(activation.context, bitmap_data);
112112
}
113-
bitmap.set_smoothing(activation.gc(), smoothing);
114-
bitmap.set_pixel_snapping(activation.gc(), pixel_snapping);
113+
bitmap.set_smoothing(smoothing);
114+
bitmap.set_pixel_snapping(pixel_snapping);
115115
} else {
116116
unreachable!();
117117
}
@@ -205,7 +205,7 @@ pub fn set_pixel_snapping<'gc>(
205205
return Err(make_error_2008(activation, "pixelSnapping"));
206206
};
207207

208-
bitmap.set_pixel_snapping(activation.gc(), pixel_snapping);
208+
bitmap.set_pixel_snapping(pixel_snapping);
209209
}
210210
Ok(Value::Undefined)
211211
}
@@ -227,15 +227,15 @@ pub fn get_smoothing<'gc>(
227227

228228
/// Implement `Bitmap.smoothing`'s setter
229229
pub fn set_smoothing<'gc>(
230-
activation: &mut Activation<'_, 'gc>,
230+
_activation: &mut Activation<'_, 'gc>,
231231
this: Value<'gc>,
232232
args: &[Value<'gc>],
233233
) -> Result<Value<'gc>, Error<'gc>> {
234234
let this = this.as_object().unwrap();
235235

236236
if let Some(bitmap) = this.as_display_object().and_then(|dobj| dobj.as_bitmap()) {
237237
let smoothing = args.get_bool(0);
238-
bitmap.set_smoothing(activation.gc(), smoothing);
238+
bitmap.set_smoothing(smoothing);
239239
}
240240

241241
Ok(Value::Undefined)

core/src/display_object/bitmap.rs

+65-54
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,17 @@ use crate::prelude::*;
1313
use crate::tag_utils::SwfMovie;
1414
use crate::vminterface::Instantiator;
1515
use core::fmt;
16-
use gc_arena::{Collect, GcCell, GcWeakCell, Mutation};
16+
use gc_arena::barrier::unlock;
17+
use gc_arena::lock::{Lock, RefLock};
18+
use gc_arena::{Collect, Gc, GcCell, GcWeak, Mutation};
1719
use ruffle_render::backend::RenderBackend;
1820
use ruffle_render::bitmap::{BitmapFormat, PixelSnapping};
19-
use std::cell::{Ref, RefMut};
21+
use std::cell::{Cell, Ref, RefMut};
2022
use std::sync::Arc;
2123

2224
#[derive(Clone, Debug, Collect, Copy)]
2325
#[collect(no_drop)]
24-
pub struct BitmapWeak<'gc>(GcWeakCell<'gc, BitmapGraphicData<'gc>>);
26+
pub struct BitmapWeak<'gc>(GcWeak<'gc, BitmapGraphicData<'gc>>);
2527

2628
impl<'gc> BitmapWeak<'gc> {
2729
pub fn upgrade(self, mc: &Mutation<'gc>) -> Option<Bitmap<'gc>> {
@@ -84,47 +86,46 @@ impl<'gc> BitmapClass<'gc> {
8486
/// It can also be created in ActionScript using the `Bitmap` class.
8587
#[derive(Clone, Collect, Copy)]
8688
#[collect(no_drop)]
87-
pub struct Bitmap<'gc>(GcCell<'gc, BitmapGraphicData<'gc>>);
89+
pub struct Bitmap<'gc>(Gc<'gc, BitmapGraphicData<'gc>>);
8890

8991
impl fmt::Debug for Bitmap<'_> {
9092
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9193
f.debug_struct("Bitmap")
92-
.field("ptr", &self.0.as_ptr())
94+
.field("ptr", &Gc::as_ptr(self.0))
9395
.finish()
9496
}
9597
}
9698

9799
#[derive(Clone, Collect)]
98100
#[collect(no_drop)]
99101
pub struct BitmapGraphicData<'gc> {
100-
base: DisplayObjectBase<'gc>,
102+
base: RefLock<DisplayObjectBase<'gc>>,
101103
id: CharacterId,
102104
movie: Arc<SwfMovie>,
103105

104106
/// The current bitmap data object.
105-
bitmap_data: BitmapDataWrapper<'gc>,
107+
bitmap_data: Lock<BitmapDataWrapper<'gc>>,
106108

107109
/// The width and height values are cached from the BitmapDataWrapper
108110
/// when this Bitmap instance is first created,
109111
/// and continue to be reported even if the BitmapData is disposed.
110-
width: u32,
111-
height: u32,
112+
width: Cell<u32>,
113+
height: Cell<u32>,
112114

113115
/// Whether or not bitmap smoothing is enabled.
114-
smoothing: bool,
116+
smoothing: Cell<bool>,
115117

116118
/// How to snap this bitmap to the pixel grid
117-
#[collect(require_static)]
118-
pixel_snapping: PixelSnapping,
119+
pixel_snapping: Cell<PixelSnapping>,
119120

120121
/// The AVM2 side of this object.
121122
///
122123
/// AVM1 code cannot directly reference `Bitmap`s, so this does not support
123124
/// storing an AVM1 object.
124-
avm2_object: Option<Avm2Object<'gc>>,
125+
avm2_object: Lock<Option<Avm2Object<'gc>>>,
125126

126127
/// The class associated with this Bitmap.
127-
avm2_bitmap_class: BitmapClass<'gc>,
128+
avm2_bitmap_class: Lock<BitmapClass<'gc>>,
128129
}
129130

130131
impl<'gc> Bitmap<'gc> {
@@ -148,18 +149,18 @@ impl<'gc> Bitmap<'gc> {
148149
let width = bitmap_data.width();
149150
let height = bitmap_data.height();
150151

151-
let bitmap = Bitmap(GcCell::new(
152+
let bitmap = Bitmap(Gc::new(
152153
mc,
153154
BitmapGraphicData {
154155
base: Default::default(),
155156
id,
156-
bitmap_data,
157-
width,
158-
height,
159-
smoothing,
160-
pixel_snapping: PixelSnapping::Auto,
161-
avm2_object: None,
162-
avm2_bitmap_class: BitmapClass::NoSubclass,
157+
bitmap_data: Lock::new(bitmap_data),
158+
width: Cell::new(width),
159+
height: Cell::new(height),
160+
smoothing: Cell::new(smoothing),
161+
pixel_snapping: Cell::new(PixelSnapping::Auto),
162+
avm2_object: Lock::new(None),
163+
avm2_bitmap_class: Lock::new(BitmapClass::NoSubclass),
163164
movie: movie.clone(),
164165
},
165166
));
@@ -205,28 +206,28 @@ impl<'gc> Bitmap<'gc> {
205206
// values on this object. See the definition of these fields
206207
// for more information
207208
pub fn width(self) -> u16 {
208-
self.0.read().width as u16
209+
self.0.width.get() as u16
209210
}
210211

211212
pub fn height(self) -> u16 {
212-
self.0.read().height as u16
213+
self.0.height.get() as u16
213214
}
214215

215216
pub fn pixel_snapping(self) -> PixelSnapping {
216-
self.0.read().pixel_snapping
217+
self.0.pixel_snapping.get()
217218
}
218219

219-
pub fn set_pixel_snapping(self, mc: &Mutation<'gc>, value: PixelSnapping) {
220-
self.0.write(mc).pixel_snapping = value;
220+
pub fn set_pixel_snapping(self, value: PixelSnapping) {
221+
self.0.pixel_snapping.set(value);
221222
}
222223

223224
pub fn bitmap_data_wrapper(self) -> BitmapDataWrapper<'gc> {
224-
self.0.read().bitmap_data
225+
self.0.bitmap_data.get()
225226
}
226227

227228
/// Retrieve the bitmap data associated with this `Bitmap`.
228229
pub fn bitmap_data(self, renderer: &mut dyn RenderBackend) -> GcCell<'gc, BitmapData<'gc>> {
229-
self.0.read().bitmap_data.sync(renderer)
230+
self.0.bitmap_data.get().sync(renderer)
230231
}
231232

232233
/// Associate this `Bitmap` with new `BitmapData`.
@@ -243,72 +244,81 @@ impl<'gc> Bitmap<'gc> {
243244
bitmap_data: BitmapDataWrapper<'gc>,
244245
) {
245246
let weak_self = DisplayObjectWeak::Bitmap(self.downgrade());
246-
let mut write = self.0.write(context.gc());
247247

248-
write
248+
self.0
249249
.bitmap_data
250+
.get()
250251
.remove_display_object(context.gc(), weak_self);
251252

252253
// Refresh our cached values, even if we're writing the same BitmapData
253254
// that we currently have stored. This will update them to '0' if the
254255
// BitmapData has been disposed since it was originally set.
255-
write.width = bitmap_data.width();
256-
write.height = bitmap_data.height();
257-
write.bitmap_data = bitmap_data;
256+
self.0.width.set(bitmap_data.width());
257+
self.0.height.set(bitmap_data.height());
258+
unlock!(
259+
Gc::write(context.gc(), self.0),
260+
BitmapGraphicData,
261+
bitmap_data
262+
)
263+
.set(bitmap_data);
258264

259265
bitmap_data.add_display_object(context.gc(), weak_self);
260266
}
261267

262268
pub fn avm2_bitmapdata_class(self) -> Option<Avm2ClassObject<'gc>> {
263-
match self.0.read().avm2_bitmap_class {
269+
match self.0.avm2_bitmap_class.get() {
264270
BitmapClass::BitmapData(c) => Some(c),
265271
_ => None,
266272
}
267273
}
268274

269275
pub fn avm2_bitmap_class(self) -> Option<Avm2ClassObject<'gc>> {
270-
match self.0.read().avm2_bitmap_class {
276+
match self.0.avm2_bitmap_class.get() {
271277
BitmapClass::Bitmap(c) => Some(c),
272278
_ => None,
273279
}
274280
}
275281

276282
pub fn set_avm2_bitmapdata_class(self, mc: &Mutation<'gc>, class: BitmapClass<'gc>) {
277-
self.0.write(mc).avm2_bitmap_class = class;
283+
unlock!(Gc::write(mc, self.0), BitmapGraphicData, avm2_bitmap_class).set(class);
284+
}
285+
286+
fn set_avm2_object(self, mc: &Mutation<'gc>, object: Option<Avm2Object<'gc>>) {
287+
unlock!(Gc::write(mc, self.0), BitmapGraphicData, avm2_object).set(object);
278288
}
279289

280290
pub fn smoothing(self) -> bool {
281-
self.0.read().smoothing
291+
self.0.smoothing.get()
282292
}
283293

284-
pub fn set_smoothing(self, mc: &Mutation<'gc>, smoothing: bool) {
285-
self.0.write(mc).smoothing = smoothing;
294+
pub fn set_smoothing(self, smoothing: bool) {
295+
self.0.smoothing.set(smoothing);
286296
}
287297

288298
pub fn downgrade(self) -> BitmapWeak<'gc> {
289-
BitmapWeak(GcCell::downgrade(self.0))
299+
BitmapWeak(Gc::downgrade(self.0))
290300
}
291301
}
292302

293303
impl<'gc> TDisplayObject<'gc> for Bitmap<'gc> {
294304
fn base(&self) -> Ref<DisplayObjectBase<'gc>> {
295-
Ref::map(self.0.read(), |r| &r.base)
305+
self.0.base.borrow()
296306
}
297307

298308
fn base_mut<'a>(&'a self, mc: &Mutation<'gc>) -> RefMut<'a, DisplayObjectBase<'gc>> {
299-
RefMut::map(self.0.write(mc), |w| &mut w.base)
309+
unlock!(Gc::write(mc, self.0), BitmapGraphicData, base).borrow_mut()
300310
}
301311

302312
fn instantiate(&self, gc_context: &Mutation<'gc>) -> DisplayObject<'gc> {
303-
Self(GcCell::new(gc_context, self.0.read().clone())).into()
313+
Self(Gc::new(gc_context, self.0.as_ref().clone())).into()
304314
}
305315

306316
fn as_ptr(&self) -> *const DisplayObjectPtr {
307-
self.0.as_ptr() as *const DisplayObjectPtr
317+
Gc::as_ptr(self.0) as *const DisplayObjectPtr
308318
}
309319

310320
fn id(&self) -> CharacterId {
311-
self.0.read().id
321+
self.0.id
312322
}
313323

314324
fn self_bounds(&self) -> Rectangle<Twips> {
@@ -345,7 +355,7 @@ impl<'gc> TDisplayObject<'gc> for Bitmap<'gc> {
345355
bitmap_cls,
346356
)
347357
.expect("can't throw from post_instantiation -_-");
348-
self.0.write(mc).avm2_object = Some(bitmap.into());
358+
self.set_avm2_object(activation.gc(), Some(bitmap.into()));
349359

350360
// Use a dummy BitmapData when calling the constructor on the user subclass
351361
// - the constructor should see an invalid BitmapData before calling 'super',
@@ -379,29 +389,30 @@ impl<'gc> TDisplayObject<'gc> for Bitmap<'gc> {
379389
return;
380390
}
381391

382-
let bitmap_data = self.0.read();
383-
bitmap_data
384-
.bitmap_data
385-
.render(bitmap_data.smoothing, context, bitmap_data.pixel_snapping);
392+
self.0.bitmap_data.get().render(
393+
self.0.smoothing.get(),
394+
context,
395+
self.0.pixel_snapping.get(),
396+
);
386397
}
387398

388399
fn object2(&self) -> Avm2Value<'gc> {
389400
self.0
390-
.read()
391401
.avm2_object
402+
.get()
392403
.map(|o| o.into())
393404
.unwrap_or(Avm2Value::Null)
394405
}
395406

396407
fn set_object2(&self, context: &mut UpdateContext<'gc>, to: Avm2Object<'gc>) {
397-
self.0.write(context.gc()).avm2_object = Some(to);
408+
self.set_avm2_object(context.gc(), Some(to));
398409
}
399410

400411
fn as_bitmap(self) -> Option<Bitmap<'gc>> {
401412
Some(self)
402413
}
403414

404415
fn movie(&self) -> Arc<SwfMovie> {
405-
self.0.read().movie.clone()
416+
self.0.movie.clone()
406417
}
407418
}

0 commit comments

Comments
 (0)