Skip to content

Commit 4fee76e

Browse files
avm2: Implement setStencilReferenceValue and setStencilActions on flash.display3D.Context3D
1 parent 67b689e commit 4fee76e

File tree

6 files changed

+296
-29
lines changed

6 files changed

+296
-29
lines changed

core/src/avm2/globals/flash/display3D/Context3D.as

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,23 +69,19 @@ package flash.display3D {
6969
return 2048;
7070
}
7171

72-
public function setStencilReferenceValue(referenceValue:uint, readMask:uint = 255, writeMask:uint = 255):void {
73-
stub_method("flash.display3D.Context3D", "setStencilReferenceValue");
74-
}
72+
public native function setStencilReferenceValue(referenceValue:uint, readMask:uint = 255, writeMask:uint = 255):void;
7573

7674
public native function setSamplerStateAt(sampler:int, wrap:String, filter:String, mipfilter:String):void;
7775

7876
public native function setRenderToTexture(texture:TextureBase, enableDepthAndStencil:Boolean = false, antiAlias:int = 0, surfaceSelector:int = 0, colorOutputIndex:int = 0):void;
7977

80-
public function setStencilActions(
78+
public native function setStencilActions(
8179
triangleFace:String = "frontAndBack",
8280
compareMode:String = "always",
8381
actionOnBothPass:String = "keep",
8482
actionOnDepthFail:String = "keep",
8583
actionOnDepthPassStencilFail:String = "keep"
86-
):void {
87-
stub_method("flash.display3D.Context3D", "setStencilActions");
88-
}
84+
):void;
8985

9086
public native function dispose(recreate:Boolean = true):void;
9187
}

core/src/avm2/globals/flash/display3D/context_3d.rs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ use crate::avm2::TObject;
99
use crate::avm2::Value;
1010
use crate::avm2_stub_method;
1111
use ruffle_macros::istr;
12-
use ruffle_render::backend::Context3DWrapMode;
1312
use ruffle_render::backend::{
1413
BufferUsage, Context3DBlendFactor, Context3DCompareMode, Context3DTextureFormat,
1514
Context3DTriangleFace, Context3DVertexBufferFormat, ProgramType,
1615
};
1716
use ruffle_render::backend::{Context3DProfile, Context3DTextureFilter};
17+
use ruffle_render::backend::{Context3DStencilAction, Context3DWrapMode};
1818
use swf::{Rectangle, Twips};
1919

2020
pub fn create_index_buffer<'gc>(
@@ -686,6 +686,59 @@ pub fn set_render_to_texture<'gc>(
686686
Ok(Value::Undefined)
687687
}
688688

689+
pub fn set_stencil_actions<'gc>(
690+
activation: &mut Activation<'_, 'gc>,
691+
this: Value<'gc>,
692+
args: &[Value<'gc>],
693+
) -> Result<Value<'gc>, Error<'gc>> {
694+
let this = this.as_object().unwrap();
695+
696+
if let Some(context) = this.as_context_3d() {
697+
let triangle_face = args.get_string_non_null(activation, 0, "triangleFace")?;
698+
699+
let culling = if &*triangle_face == b"none" {
700+
Context3DTriangleFace::None
701+
} else if &*triangle_face == b"back" {
702+
Context3DTriangleFace::Back
703+
} else if &*triangle_face == b"front" {
704+
Context3DTriangleFace::Front
705+
} else if &*triangle_face == b"frontAndBack" {
706+
Context3DTriangleFace::FrontAndBack
707+
} else {
708+
tracing::error!("Unknown culling {:?}", triangle_face);
709+
Context3DTriangleFace::None
710+
};
711+
712+
let compare_mode = args.get_string_non_null(activation, 1, "compareMode")?;
713+
let compare_mode = Context3DCompareMode::from_wstr(&compare_mode)
714+
.ok_or_else(|| make_error_2008(activation, "compareMode"))?;
715+
716+
let action_on_both_pass = args.get_string_non_null(activation, 2, "actionOnBothPass")?;
717+
let action_on_both_pass = Context3DStencilAction::from_wstr(&action_on_both_pass)
718+
.ok_or_else(|| make_error_2008(activation, "actionOnBothPass"))?;
719+
720+
let action_on_depth_fail = args.get_string_non_null(activation, 3, "actionOnDepthFail")?;
721+
let action_on_depth_fail = Context3DStencilAction::from_wstr(&action_on_depth_fail)
722+
.ok_or_else(|| make_error_2008(activation, "actionOnDepthFail"))?;
723+
724+
let action_on_depth_pass_stencil_fail =
725+
args.get_string_non_null(activation, 4, "actionOnDepthPassStencilFail")?;
726+
let action_on_depth_pass_stencil_fail =
727+
Context3DStencilAction::from_wstr(&action_on_depth_pass_stencil_fail)
728+
.ok_or_else(|| make_error_2008(activation, "actionOnDepthPassStencilFail"))?;
729+
730+
context.set_stencil_actions(
731+
culling,
732+
compare_mode,
733+
action_on_both_pass,
734+
action_on_depth_fail,
735+
action_on_depth_pass_stencil_fail,
736+
);
737+
}
738+
739+
Ok(Value::Undefined)
740+
}
741+
689742
pub fn set_render_to_back_buffer<'gc>(
690743
_activation: &mut Activation<'_, 'gc>,
691744
this: Value<'gc>,
@@ -697,6 +750,23 @@ pub fn set_render_to_back_buffer<'gc>(
697750
context.set_render_to_back_buffer();
698751
Ok(Value::Undefined)
699752
}
753+
pub fn set_stencil_reference_value<'gc>(
754+
activation: &mut Activation<'_, 'gc>,
755+
this: Value<'gc>,
756+
args: &[Value<'gc>],
757+
) -> Result<Value<'gc>, Error<'gc>> {
758+
let this = this.as_object().unwrap();
759+
760+
if let Some(context) = this.as_context_3d() {
761+
let reference_value = args.get_u32(activation, 0)?;
762+
let read_mask = args.get_u32(activation, 1)?;
763+
let write_mask = args.get_u32(activation, 2)?;
764+
765+
context.set_stencil_reference_value(reference_value, read_mask, write_mask);
766+
}
767+
768+
Ok(Value::Undefined)
769+
}
700770

701771
pub fn set_sampler_state_at<'gc>(
702772
activation: &mut Activation<'_, 'gc>,

core/src/avm2/object/context3d_object.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use crate::utils::HasPrefixField;
1212
use gc_arena::{Collect, Gc, GcCell, GcWeak};
1313
use ruffle_render::backend::{
1414
BufferUsage, Context3D, Context3DBlendFactor, Context3DCommand, Context3DCompareMode,
15-
Context3DTextureFormat, Context3DTriangleFace, Context3DVertexBufferFormat, ProgramType,
16-
Texture,
15+
Context3DStencilAction, Context3DTextureFormat, Context3DTriangleFace,
16+
Context3DVertexBufferFormat, ProgramType, Texture,
1717
};
1818
use ruffle_render::commands::CommandHandler;
1919
use std::cell::Cell;
@@ -476,6 +476,40 @@ impl<'gc> Context3DObject<'gc> {
476476
ctx.process_command(Context3DCommand::SetScissorRectangle { rect })
477477
});
478478
}
479+
480+
pub(crate) fn set_stencil_actions(
481+
&self,
482+
triangle_face: Context3DTriangleFace,
483+
compare_mode: Context3DCompareMode,
484+
action_on_both_pass: Context3DStencilAction,
485+
action_on_depth_fail: Context3DStencilAction,
486+
action_on_depth_pass_stencil_fail: Context3DStencilAction,
487+
) {
488+
self.with_context_3d(|ctx| {
489+
ctx.process_command(Context3DCommand::SetStencilActions {
490+
triangle_face,
491+
compare_mode,
492+
action_on_both_pass,
493+
action_on_depth_fail,
494+
action_on_depth_pass_stencil_fail,
495+
})
496+
});
497+
}
498+
499+
pub(crate) fn set_stencil_reference_value(
500+
&self,
501+
reference_value: u32,
502+
read_mask: u32,
503+
write_mask: u32,
504+
) {
505+
self.with_context_3d(|ctx| {
506+
ctx.process_command(Context3DCommand::SetStencilReferenceValue {
507+
reference_value,
508+
read_mask,
509+
write_mask,
510+
})
511+
});
512+
}
479513
}
480514

481515
#[derive(Collect, HasPrefixField)]

render/src/backend.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,74 @@ impl Context3DCompareMode {
362362
}
363363
}
364364

365+
#[cfg(feature = "wgpu")]
366+
impl From<Context3DCompareMode> for wgpu::CompareFunction {
367+
fn from(mode: Context3DCompareMode) -> Self {
368+
match mode {
369+
Context3DCompareMode::Never => wgpu::CompareFunction::Never,
370+
Context3DCompareMode::Less => wgpu::CompareFunction::Less,
371+
Context3DCompareMode::Equal => wgpu::CompareFunction::Equal,
372+
Context3DCompareMode::LessEqual => wgpu::CompareFunction::LessEqual,
373+
Context3DCompareMode::Greater => wgpu::CompareFunction::Greater,
374+
Context3DCompareMode::NotEqual => wgpu::CompareFunction::NotEqual,
375+
Context3DCompareMode::GreaterEqual => wgpu::CompareFunction::GreaterEqual,
376+
Context3DCompareMode::Always => wgpu::CompareFunction::Always,
377+
}
378+
}
379+
}
380+
381+
#[derive(Copy, Clone, Debug)]
382+
pub enum Context3DStencilAction {
383+
DecrementSaturate,
384+
DecrementWrap,
385+
IncrementSaturate,
386+
IncrementWrap,
387+
Invert,
388+
Keep,
389+
Set,
390+
Zero,
391+
}
392+
393+
impl Context3DStencilAction {
394+
pub fn from_wstr(s: &WStr) -> Option<Self> {
395+
if s == b"decrementSaturate" {
396+
Some(Context3DStencilAction::DecrementSaturate)
397+
} else if s == b"decrementWrap" {
398+
Some(Context3DStencilAction::DecrementWrap)
399+
} else if s == b"incrementSaturate" {
400+
Some(Context3DStencilAction::IncrementSaturate)
401+
} else if s == b"incrementWrap" {
402+
Some(Context3DStencilAction::IncrementWrap)
403+
} else if s == b"invert" {
404+
Some(Context3DStencilAction::Invert)
405+
} else if s == b"keep" {
406+
Some(Context3DStencilAction::Keep)
407+
} else if s == b"set" {
408+
Some(Context3DStencilAction::Set)
409+
} else if s == b"zero" {
410+
Some(Context3DStencilAction::Zero)
411+
} else {
412+
None
413+
}
414+
}
415+
}
416+
417+
#[cfg(feature = "wgpu")]
418+
impl From<Context3DStencilAction> for wgpu::StencilOperation {
419+
fn from(action: Context3DStencilAction) -> Self {
420+
match action {
421+
Context3DStencilAction::DecrementSaturate => wgpu::StencilOperation::DecrementClamp,
422+
Context3DStencilAction::DecrementWrap => wgpu::StencilOperation::DecrementWrap,
423+
Context3DStencilAction::IncrementSaturate => wgpu::StencilOperation::IncrementClamp,
424+
Context3DStencilAction::IncrementWrap => wgpu::StencilOperation::IncrementWrap,
425+
Context3DStencilAction::Invert => wgpu::StencilOperation::Invert,
426+
Context3DStencilAction::Keep => wgpu::StencilOperation::Keep,
427+
Context3DStencilAction::Set => wgpu::StencilOperation::Replace,
428+
Context3DStencilAction::Zero => wgpu::StencilOperation::Zero,
429+
}
430+
}
431+
}
432+
365433
#[derive(Copy, Clone, Debug)]
366434
pub enum Context3DWrapMode {
367435
Clamp,
@@ -517,6 +585,18 @@ pub enum Context3DCommand<'a> {
517585
SetScissorRectangle {
518586
rect: Option<Rectangle<Twips>>,
519587
},
588+
SetStencilActions {
589+
triangle_face: Context3DTriangleFace,
590+
compare_mode: Context3DCompareMode,
591+
action_on_both_pass: Context3DStencilAction,
592+
action_on_depth_fail: Context3DStencilAction,
593+
action_on_depth_pass_stencil_fail: Context3DStencilAction,
594+
},
595+
SetStencilReferenceValue {
596+
reference_value: u32,
597+
read_mask: u32,
598+
write_mask: u32,
599+
},
520600
}
521601

522602
#[derive(Clone, Debug)]

0 commit comments

Comments
 (0)