Skip to content

Commit c3fe642

Browse files
committed
core: use OnceCell for lazily-loaded Drawings in display objects
This saves one `usize` in the common case where there's no `Drawing`
1 parent 4d6d99a commit c3fe642

File tree

2 files changed

+17
-20
lines changed

2 files changed

+17
-20
lines changed

core/src/display_object/graphic.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use gc_arena::barrier::unlock;
1515
use gc_arena::{Collect, Gc, Lock, Mutation, RefLock};
1616
use ruffle_render::backend::ShapeHandle;
1717
use ruffle_render::commands::CommandHandler;
18-
use std::cell::{Ref, RefCell, RefMut};
18+
use std::cell::{OnceCell, Ref, RefCell, RefMut};
1919
use std::sync::Arc;
2020

2121
#[derive(Clone, Collect, Copy)]
@@ -38,7 +38,8 @@ pub struct GraphicData<'gc> {
3838
class: Lock<Option<Avm2ClassObject<'gc>>>,
3939
avm2_object: Lock<Option<Avm2Object<'gc>>>,
4040
/// This is lazily allocated on demand, to make `GraphicData` smaller in the common case.
41-
drawing: RefCell<Option<Box<Drawing>>>,
41+
#[collect(require_static)]
42+
drawing: OnceCell<Box<RefCell<Drawing>>>,
4243
}
4344

4445
impl<'gc> Graphic<'gc> {
@@ -68,7 +69,7 @@ impl<'gc> Graphic<'gc> {
6869
shared: Lock::new(Gc::new(context.gc(), shared)),
6970
class: Lock::new(None),
7071
avm2_object: Lock::new(None),
71-
drawing: RefCell::new(None),
72+
drawing: OnceCell::new(),
7273
},
7374
))
7475
}
@@ -101,15 +102,13 @@ impl<'gc> Graphic<'gc> {
101102
shared: Lock::new(Gc::new(context.gc(), shared)),
102103
class: Lock::new(None),
103104
avm2_object: Lock::new(None),
104-
drawing: RefCell::new(None),
105+
drawing: OnceCell::new(),
105106
},
106107
))
107108
}
108109

109110
pub fn drawing_mut(&self) -> RefMut<'_, Drawing> {
110-
RefMut::map(self.0.drawing.borrow_mut(), |drawing| {
111-
&mut **drawing.get_or_insert_with(Default::default)
112-
})
111+
self.0.drawing.get_or_init(Default::default).borrow_mut()
113112
}
114113

115114
pub fn set_avm2_class(self, mc: &Mutation<'gc>, class: Avm2ClassObject<'gc>) {
@@ -143,8 +142,8 @@ impl<'gc> TDisplayObject<'gc> for Graphic<'gc> {
143142
}
144143

145144
fn self_bounds(self) -> Rectangle<Twips> {
146-
if let Some(drawing) = self.0.drawing.borrow().as_ref() {
147-
drawing.self_bounds()
145+
if let Some(drawing) = self.0.drawing.get() {
146+
drawing.borrow().self_bounds()
148147
} else {
149148
self.0.shared.get().bounds
150149
}
@@ -200,8 +199,8 @@ impl<'gc> TDisplayObject<'gc> for Graphic<'gc> {
200199
return;
201200
}
202201

203-
if let Some(drawing) = &self.0.drawing.borrow().as_ref() {
204-
drawing.render(context);
202+
if let Some(drawing) = self.0.drawing.get() {
203+
drawing.borrow().render(context);
205204
} else if let Some(render_handle) = self.0.shared.get().render_handle.clone() {
206205
context
207206
.commands
@@ -223,8 +222,8 @@ impl<'gc> TDisplayObject<'gc> for Graphic<'gc> {
223222
return false;
224223
};
225224
let point = local_matrix * point;
226-
if let Some(drawing) = &self.0.drawing.borrow().as_ref() {
227-
if drawing.hit_test(point, &local_matrix) {
225+
if let Some(drawing) = self.0.drawing.get() {
226+
if drawing.borrow().hit_test(point, &local_matrix) {
228227
return true;
229228
}
230229
} else {

core/src/display_object/movie_clip.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use ruffle_macros::istr;
4646
use ruffle_render::perspective_projection::PerspectiveProjection;
4747
use smallvec::SmallVec;
4848
use std::borrow::Cow;
49-
use std::cell::{Cell, Ref, RefCell, RefMut};
49+
use std::cell::{Cell, OnceCell, Ref, RefCell, RefMut};
5050
use std::cmp::max;
5151
use std::collections::HashMap;
5252
use std::sync::Arc;
@@ -165,7 +165,7 @@ pub struct MovieClipData<'gc> {
165165
flags: Cell<MovieClipFlags>,
166166
/// This is lazily allocated on demand, to make `MovieClipData` smaller in the common case.
167167
#[collect(require_static)]
168-
drawing: RefCell<Option<Box<Drawing>>>,
168+
drawing: OnceCell<Box<RefCell<Drawing>>>,
169169
avm2_enabled: Cell<bool>,
170170

171171
/// Show a hand cursor when the clip is in button mode.
@@ -211,7 +211,7 @@ impl<'gc> MovieClipData<'gc> {
211211
clip_event_flags: Cell::new(ClipEventFlag::empty()),
212212
frame_scripts: RefLock::new(Vec::new()),
213213
flags: Cell::new(MovieClipFlags::empty()),
214-
drawing: RefCell::new(None),
214+
drawing: OnceCell::new(),
215215
avm2_enabled: Cell::new(true),
216216
avm2_use_hand_cursor: Cell::new(true),
217217
button_mode: Cell::new(false),
@@ -1945,13 +1945,11 @@ impl<'gc> MovieClip<'gc> {
19451945
pub fn drawing_mut(&self, gc_context: &Mutation<'gc>) -> RefMut<'_, Drawing> {
19461946
// We're about to change graphics, so invalidate on the next frame
19471947
self.invalidate_cached_bitmap(gc_context);
1948-
RefMut::map(self.0.drawing.borrow_mut(), |drawing| {
1949-
&mut **drawing.get_or_insert_with(Default::default)
1950-
})
1948+
self.0.drawing.get_or_init(Default::default).borrow_mut()
19511949
}
19521950

19531951
pub fn drawing(&self) -> Option<Ref<'_, Drawing>> {
1954-
Ref::filter_map(self.0.drawing.borrow(), |d| d.as_deref()).ok()
1952+
self.0.drawing.get().map(|d| d.borrow())
19551953
}
19561954

19571955
pub fn is_button_mode(&self, context: &mut UpdateContext<'gc>) -> bool {

0 commit comments

Comments
 (0)