From e3a599a27d4b1ac3fddd0d14cd9c80ec36dc2baf Mon Sep 17 00:00:00 2001 From: Lord-McSweeney Date: Mon, 9 Dec 2024 16:23:42 -0800 Subject: [PATCH] avm2: Use slot access in native code for ShaderJob --- .../avm2/globals/flash/display/ShaderInput.as | 10 ++- .../avm2/globals/flash/display/shader_job.rs | 61 +++++++++++-------- core/src/avm2/object.rs | 12 +++- 3 files changed, 53 insertions(+), 30 deletions(-) diff --git a/core/src/avm2/globals/flash/display/ShaderInput.as b/core/src/avm2/globals/flash/display/ShaderInput.as index ab199f486849..2ce1c69c514d 100644 --- a/core/src/avm2/globals/flash/display/ShaderInput.as +++ b/core/src/avm2/globals/flash/display/ShaderInput.as @@ -3,12 +3,16 @@ package flash.display { [Ruffle(InternalSlot)] private var _channels: int; + [Ruffle(InternalSlot)] private var _height: int; [Ruffle(InternalSlot)] private var _index: int; - private var _object: Object; + [Ruffle(InternalSlot)] + private var _input: Object; + + [Ruffle(InternalSlot)] private var _width: int; public function get channels():int { @@ -36,12 +40,12 @@ package flash.display { } public function get input():Object { - return _object; + return this._input; } public function set input(value:Object):void { // FIXME - validate - _object = value; + this._input = value; } } } diff --git a/core/src/avm2/globals/flash/display/shader_job.rs b/core/src/avm2/globals/flash/display/shader_job.rs index d15440bd441e..e801c93132f6 100644 --- a/core/src/avm2/globals/flash/display/shader_job.rs +++ b/core/src/avm2/globals/flash/display/shader_job.rs @@ -1,6 +1,8 @@ use crate::avm2::bytearray::Endian; use crate::avm2::globals::slots::{ - flash_display_shader as shader_slots, flash_display_shader_job as shader_job_slots, + flash_display_shader as shader_slots, flash_display_shader_input as shader_input_slots, + flash_display_shader_job as shader_job_slots, + flash_display_shader_parameter as shader_parameter_slots, }; use crate::avm2::parameters::ParametersExt; use crate::avm2::{Activation, Error, Object, TObject, Value}; @@ -65,7 +67,7 @@ pub fn get_shader_args<'gc>( }); } let shader_param = shader_data - .get_public_property( + .get_string_property_local( AvmString::new_utf8(activation.context.gc_context, name), activation, ) @@ -75,9 +77,18 @@ pub fn get_shader_args<'gc>( .as_object() .expect("Shader property is not an object"); - let value = shader_param - .get_public_property("value", activation) - .expect("Missing value property"); + if !shader_param.is_of_type( + activation + .avm2() + .classes() + .shaderparameter + .inner_class_definition(), + ) { + panic!("Expected shader parameter to be of class ShaderParameter"); + } + + let value = shader_param.get_slot(shader_parameter_slots::_VALUE); + let pb_val = PixelBenderType::from_avm2_value(activation, value, param_type) .expect("Failed to convert AVM2 value to PixelBenderType"); @@ -92,7 +103,7 @@ pub fn get_shader_args<'gc>( name, } => { let shader_input = shader_data - .get_public_property( + .get_string_property_local( AvmString::new_utf8(activation.context.gc_context, name), activation, ) @@ -100,33 +111,28 @@ pub fn get_shader_args<'gc>( .as_object() .expect("Shader input is not an object"); - let input = shader_input - .get_public_property("input", activation) - .expect("Missing input property"); + if !shader_input.is_of_type( + activation + .avm2() + .classes() + .shaderinput + .inner_class_definition(), + ) { + panic!("Expected shader input to be of class ShaderInput"); + } - let width = shader_input - .get_public_property("width", activation) - .unwrap() - .as_u32(); - let height = shader_input - .get_public_property("height", activation) - .unwrap() - .as_u32(); + let input = shader_input.get_slot(shader_input_slots::_INPUT); + + let width = shader_input.get_slot(shader_input_slots::_WIDTH).as_u32(); + let height = shader_input.get_slot(shader_input_slots::_HEIGHT).as_u32(); let input_channels = shader_input - .get_public_property("channels", activation) - .unwrap() + .get_slot(shader_input_slots::_CHANNELS) .as_u32(); assert_eq!(*channels as u32, input_channels); - let texture = if let Value::Null = input { - None - } else { - let input = input - .as_object() - .expect("ShaderInput.input is not an object"); - + let texture = if let Some(input) = input.as_object() { let input_texture = if let Some(bitmap) = input.as_bitmap_data() { ImageInputTexture::Bitmap(bitmap.bitmap_handle( activation.context.gc_context, @@ -159,6 +165,9 @@ pub fn get_shader_args<'gc>( panic!("Unexpected input object {input:?}"); }; Some(input_texture) + } else { + // Null input + None }; Some(PixelBenderShaderArgument::ImageInput { diff --git a/core/src/avm2/object.rs b/core/src/avm2/object.rs index 144593208a8d..b322aacbe2cf 100644 --- a/core/src/avm2/object.rs +++ b/core/src/avm2/object.rs @@ -234,6 +234,16 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy self.base().get_property_local(name, activation) } + /// Same as get_property_local, but constructs a public Multiname for you. + fn get_string_property_local( + self, + name: impl Into>, + activation: &mut Activation<'_, 'gc>, + ) -> Result, Error<'gc>> { + let name = Multiname::new(activation.avm2().namespaces.public_vm_internal(), name); + self.get_property_local(&name, activation) + } + /// Retrieve a property by Multiname lookup. /// /// This method should not be overridden. @@ -321,7 +331,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy base.set_property_local(name, value, activation) } - /// Same as get_property_local, but constructs a public Multiname for you. + /// Same as set_property_local, but constructs a public Multiname for you. /// TODO: this feels upside down, as in: we shouldn't need multinames/namespaces /// by the time we reach dynamic properties. /// But for now, this function is a smaller change to the core than a full refactor.