core: Invalidate cacheAsBitmap when transform changes

This commit is contained in:
Nathan Adams 2023-06-18 22:05:01 +02:00
parent 0f01efb322
commit 27db3e70b4
17 changed files with 64 additions and 7 deletions

View File

@ -1608,6 +1608,12 @@ fn set_transform<'gc>(
let color_transform = *clip.base().color_transform(); let color_transform = *clip.base().color_transform();
this.set_color_transform(activation.context.gc_context, color_transform); this.set_color_transform(activation.context.gc_context, color_transform);
if let Some(parent) = this.parent() {
// Self-transform changes are automatically handled,
// we only want to inform ancestors to avoid unnecessary invalidations for tx/ty
parent.invalidate_cached_bitmap(activation.context.gc_context);
}
this.set_transformed_by_script(activation.context.gc_context, true); this.set_transformed_by_script(activation.context.gc_context, true);
} }
} }

View File

@ -97,6 +97,11 @@ fn method<'gc>(
let matrix = object_to_matrix(object, activation)?; let matrix = object_to_matrix(object, activation)?;
clip.set_matrix(activation.context.gc_context, matrix); clip.set_matrix(activation.context.gc_context, matrix);
clip.set_transformed_by_script(activation.context.gc_context, true); clip.set_transformed_by_script(activation.context.gc_context, true);
if let Some(parent) = clip.parent() {
// Self-transform changes are automatically handled,
// we only want to inform ancestors to avoid unnecessary invalidations for tx/ty
parent.invalidate_cached_bitmap(activation.context.gc_context);
}
} }
} }
Value::Undefined Value::Undefined
@ -120,6 +125,7 @@ fn method<'gc>(
activation.context.gc_context, activation.context.gc_context,
color_transform.read().clone().into(), color_transform.read().clone().into(),
); );
clip.invalidate_cached_bitmap(activation.context.gc_context);
clip.set_transformed_by_script(activation.context.gc_context, true); clip.set_transformed_by_script(activation.context.gc_context, true);
} }
} }

View File

@ -731,6 +731,12 @@ pub fn set_transform<'gc>(
let mut write = dobj.base_mut(activation.context.gc_context); let mut write = dobj.base_mut(activation.context.gc_context);
write.set_matrix(matrix); write.set_matrix(matrix);
write.set_color_transform(color_transform); write.set_color_transform(color_transform);
drop(write);
if let Some(parent) = dobj.parent() {
// Self-transform changes are automatically handled,
// we only want to inform ancestors to avoid unnecessary invalidations for tx/ty
parent.invalidate_cached_bitmap(activation.context.gc_context);
}
} }
Ok(Value::Undefined) Ok(Value::Undefined)
} }

View File

@ -53,9 +53,9 @@ pub fn set_color_transform<'gc>(
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
let this = this.unwrap(); let this = this.unwrap();
let ct = object_to_color_transform(args.get_object(activation, 0, "value")?, activation)?; let ct = object_to_color_transform(args.get_object(activation, 0, "value")?, activation)?;
get_display_object(this, activation)? let dobj = get_display_object(this, activation)?;
.base_mut(activation.context.gc_context) dobj.set_color_transform(activation.context.gc_context, ct);
.set_color_transform(ct); dobj.invalidate_cached_bitmap(activation.context.gc_context);
Ok(Value::Undefined) Ok(Value::Undefined)
} }
@ -76,9 +76,13 @@ pub fn set_matrix<'gc>(
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
let this = this.unwrap(); let this = this.unwrap();
let matrix = object_to_matrix(args.get_object(activation, 0, "value")?, activation)?; let matrix = object_to_matrix(args.get_object(activation, 0, "value")?, activation)?;
get_display_object(this, activation)? let dobj = get_display_object(this, activation)?;
.base_mut(activation.context.gc_context) dobj.set_matrix(activation.context.gc_context, matrix);
.set_matrix(matrix); if let Some(parent) = dobj.parent() {
// Self-transform changes are automatically handled,
// we only want to inform ancestors to avoid unnecessary invalidations for tx/ty
parent.invalidate_cached_bitmap(activation.context.gc_context);
}
Ok(Value::Undefined) Ok(Value::Undefined)
} }

View File

@ -941,10 +941,16 @@ pub trait TDisplayObject<'gc>:
self.base_mut(gc_context).set_place_frame(frame) self.base_mut(gc_context).set_place_frame(frame)
} }
/// Sets the matrix of this object.
/// This does NOT invalidate the cache, as it's often used with other operations.
/// It is the callers responsibility to do so.
fn set_matrix(&self, gc_context: MutationContext<'gc, '_>, matrix: Matrix) { fn set_matrix(&self, gc_context: MutationContext<'gc, '_>, matrix: Matrix) {
self.base_mut(gc_context).set_matrix(matrix); self.base_mut(gc_context).set_matrix(matrix);
} }
/// Sets the color transform of this object.
/// This does NOT invalidate the cache, as it's often used with other operations.
/// It is the callers responsibility to do so.
fn set_color_transform( fn set_color_transform(
&self, &self,
gc_context: MutationContext<'gc, '_>, gc_context: MutationContext<'gc, '_>,
@ -1184,8 +1190,13 @@ pub trait TDisplayObject<'gc>:
/// Sets the opacity of this display object. /// Sets the opacity of this display object.
/// 1 is fully opaque. /// 1 is fully opaque.
/// Set by the `_alpha`/`alpha` ActionScript properties. /// Set by the `_alpha`/`alpha` ActionScript properties.
/// This invalidates any cacheAsBitmap automatically.
fn set_alpha(&self, gc_context: MutationContext<'gc, '_>, value: f64) { fn set_alpha(&self, gc_context: MutationContext<'gc, '_>, value: f64) {
self.base_mut(gc_context).set_alpha(value) self.base_mut(gc_context).set_alpha(value);
if let Some(parent) = self.parent() {
// Self-transform changes are automatically handled
parent.invalidate_cached_bitmap(gc_context);
}
} }
fn name(&self) -> AvmString<'gc> { fn name(&self) -> AvmString<'gc> {
@ -1765,9 +1776,15 @@ pub trait TDisplayObject<'gc>:
if !self.transformed_by_script() { if !self.transformed_by_script() {
if let Some(matrix) = place_object.matrix { if let Some(matrix) = place_object.matrix {
self.set_matrix(context.gc_context, matrix.into()); self.set_matrix(context.gc_context, matrix.into());
if let Some(parent) = self.parent() {
// Self-transform changes are automatically handled,
// we only want to inform ancestors to avoid unnecessary invalidations for tx/ty
parent.invalidate_cached_bitmap(context.gc_context);
}
} }
if let Some(color_transform) = &place_object.color_transform { if let Some(color_transform) = &place_object.color_transform {
self.set_color_transform(context.gc_context, *color_transform); self.set_color_transform(context.gc_context, *color_transform);
self.invalidate_cached_bitmap(context.gc_context);
} }
if let Some(ratio) = place_object.ratio { if let Some(ratio) = place_object.ratio {
if let Some(mut morph_shape) = self.as_morph_shape() { if let Some(mut morph_shape) = self.as_morph_shape() {

View File

@ -191,6 +191,8 @@ impl<'gc> Avm1Button<'gc> {
dispatch_removed_event(removed_child, context); dispatch_removed_event(removed_child, context);
} }
} }
self.invalidate_cached_bitmap(context.gc_context);
} }
fn get_boolean_property( fn get_boolean_property(

View File

@ -227,6 +227,8 @@ impl<'gc> Avm2Button<'gc> {
} }
} }
self.invalidate_cached_bitmap(context.gc_context);
// We manually call `construct_frame` for `child` and `state_sprite` - normally // We manually call `construct_frame` for `child` and `state_sprite` - normally
// this would be done in the `DisplayObject` constructor, but SimpleButton does // this would be done in the `DisplayObject` constructor, but SimpleButton does
// not have children in the normal DisplayObjectContainer sense. // not have children in the normal DisplayObjectContainer sense.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -0,0 +1,7 @@
num_frames = 3
[image_comparison]
tolerance = 0
[player_options]
with_renderer = { optional = false, sample_count = 1 }

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,7 @@
num_frames = 3
[image_comparison]
tolerance = 0
[player_options]
with_renderer = { optional = false, sample_count = 1 }