Skip to content

Commit

Permalink
avm2: Use slot access in native code for ShaderJob
Browse files Browse the repository at this point in the history
  • Loading branch information
Lord-McSweeney authored and Lord-McSweeney committed Dec 10, 2024
1 parent 6bd4fa1 commit e3a599a
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 30 deletions.
10 changes: 7 additions & 3 deletions core/src/avm2/globals/flash/display/ShaderInput.as
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}
}
}
61 changes: 35 additions & 26 deletions core/src/avm2/globals/flash/display/shader_job.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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,
)
Expand All @@ -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");

Expand All @@ -92,41 +103,36 @@ 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,
)
.expect("Missing property")
.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,
Expand Down Expand Up @@ -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 {
Expand Down
12 changes: 11 additions & 1 deletion core/src/avm2/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,16 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + 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<AvmString<'gc>>,
activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, 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.
Expand Down Expand Up @@ -321,7 +331,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + 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.
Expand Down

0 comments on commit e3a599a

Please sign in to comment.