diff --git a/Cargo.lock b/Cargo.lock index 5c7695717163..b798ee907cd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3862,6 +3862,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pixel_bender" +version = "0.1.0" +dependencies = [ + "byteorder", + "num-derive", + "num-traits", + "thiserror 2.0.12", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -4575,6 +4585,7 @@ dependencies = [ "lyon_geom", "num-derive", "num-traits", + "pixel_bender", "png", "renderdoc", "ruffle_wstr", diff --git a/Cargo.toml b/Cargo.toml index 0b6f5850f9e5..b18d8ff7aaba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ members = [ "render", "render/canvas", "render/naga-agal", + "render/pixel_bender", "render/wgpu", "render/webgl", diff --git a/core/src/avm2/globals/flash/display/shader_job.rs b/core/src/avm2/globals/flash/display/shader_job.rs index 1c0ae8bf9cfe..48148b470a7c 100644 --- a/core/src/avm2/globals/flash/display/shader_job.rs +++ b/core/src/avm2/globals/flash/display/shader_job.rs @@ -15,9 +15,10 @@ use crate::avm2_stub_method; use ruffle_render::backend::{PixelBenderOutput, PixelBenderTarget}; use ruffle_render::bitmap::PixelRegion; use ruffle_render::pixel_bender::{ - ImageInputTexture, PixelBenderParam, PixelBenderParamQualifier, PixelBenderShaderArgument, - PixelBenderShaderHandle, PixelBenderType, OUT_COORD_NAME, + PixelBenderParam, PixelBenderParamQualifier, PixelBenderShaderHandle, PixelBenderType, + OUT_COORD_NAME, }; +use ruffle_render::pixel_bender_support::{ImageInputTexture, PixelBenderShaderArgument}; pub fn get_shader_args<'gc>( shader_obj: Object<'gc>, diff --git a/render/Cargo.toml b/render/Cargo.toml index 906eda6bf648..c12afdf4d6de 100644 --- a/render/Cargo.toml +++ b/render/Cargo.toml @@ -13,6 +13,7 @@ workspace = true [dependencies] ruffle_wstr = { path = "../wstr" } swf = { path = "../swf"} +pixel_bender = { path = "pixel_bender"} tracing = { workspace = true } gif = "0.13.3" png = "0.17.16" diff --git a/render/canvas/src/lib.rs b/render/canvas/src/lib.rs index 9d1705af18fa..72841c7f35e5 100644 --- a/render/canvas/src/lib.rs +++ b/render/canvas/src/lib.rs @@ -574,7 +574,7 @@ impl RenderBackend for WebCanvasRenderBackend { fn run_pixelbender_shader( &mut self, _handle: ruffle_render::pixel_bender::PixelBenderShaderHandle, - _arguments: &[ruffle_render::pixel_bender::PixelBenderShaderArgument], + _arguments: &[ruffle_render::pixel_bender_support::PixelBenderShaderArgument], _target: &PixelBenderTarget, ) -> Result { Err(Error::Unimplemented("run_pixelbender_shader".into())) diff --git a/render/naga-pixelbender/Cargo.toml b/render/naga-pixelbender/Cargo.toml index 9a8770e49b82..88c822b57bad 100644 --- a/render/naga-pixelbender/Cargo.toml +++ b/render/naga-pixelbender/Cargo.toml @@ -14,4 +14,3 @@ workspace = true ruffle_render = { path = "../" } naga = { workspace = true } anyhow = { workspace = true } - diff --git a/render/pixel_bender/Cargo.toml b/render/pixel_bender/Cargo.toml new file mode 100644 index 000000000000..34db99d27c71 --- /dev/null +++ b/render/pixel_bender/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "pixel_bender" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +repository.workspace = true +version.workspace = true + +[lints] +workspace = true + +[dependencies] +thiserror = { workspace = true } +num-traits = { workspace = true } +num-derive = { workspace = true } +byteorder = { workspace = true } diff --git a/render/src/pixel_bender/disassembly.rs b/render/pixel_bender/src/disassembly.rs similarity index 99% rename from render/src/pixel_bender/disassembly.rs rename to render/pixel_bender/src/disassembly.rs index fc6481ad5f47..2c212a87568c 100644 --- a/render/src/pixel_bender/disassembly.rs +++ b/render/pixel_bender/src/disassembly.rs @@ -1,6 +1,6 @@ use std::fmt::{Display, Formatter}; -use crate::pixel_bender::{ +use crate::parser::{ Opcode, Operation, PixelBenderMetadata, PixelBenderParam, PixelBenderParamQualifier, PixelBenderReg, PixelBenderRegChannel, PixelBenderRegKind, PixelBenderShader, PixelBenderType, PixelBenderTypeOpcode, diff --git a/render/pixel_bender/src/lib.rs b/render/pixel_bender/src/lib.rs new file mode 100644 index 000000000000..63676994139f --- /dev/null +++ b/render/pixel_bender/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests; + +pub mod disassembly; +mod parser; + +pub use parser::*; diff --git a/render/src/pixel_bender.rs b/render/pixel_bender/src/parser.rs similarity index 94% rename from render/src/pixel_bender.rs rename to render/pixel_bender/src/parser.rs index 57e75653f6d8..640a1e4b1d65 100644 --- a/render/src/pixel_bender.rs +++ b/render/pixel_bender/src/parser.rs @@ -1,11 +1,6 @@ //! Pixel bender bytecode parsing code. //! This is heavily based on https://github.com/jamesward/pbjas and https://github.com/HaxeFoundation/format/tree/master/format/pbj -#[cfg(test)] -mod tests; - -pub mod disassembly; - use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; use num_traits::FromPrimitive; use std::{ @@ -16,8 +11,6 @@ use std::{ }; use thiserror::Error; -use crate::{backend::RawTexture, bitmap::BitmapHandle}; - /// The name of a special parameter, which gets automatically filled in with the coordinates /// of the pixel being processed. pub const OUT_COORD_NAME: &str = "_OutCoord"; @@ -307,61 +300,6 @@ pub enum Operation { }, } -#[derive(Debug, Clone, PartialEq)] -pub enum PixelBenderShaderArgument<'a> { - ImageInput { - index: u8, - channels: u8, - name: String, - texture: Option>, - }, - ValueInput { - index: u8, - value: PixelBenderType, - }, -} - -/// An image input. -/// -/// This accepts both an owned BitmapHandle, and a borrowed texture -/// (used when applying a filter to a texture that we don't have -/// ownership of, and therefore cannot construct a BitmapHandle for). -#[derive(Debug, Clone)] -pub enum ImageInputTexture<'a> { - Bitmap(BitmapHandle), - TextureRef(&'a dyn RawTexture), - Bytes { - width: u32, - height: u32, - channels: u32, - bytes: Vec, - }, -} - -impl PartialEq for ImageInputTexture<'_> { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Self::Bitmap(self_bitmap), Self::Bitmap(other_bitmap)) => self_bitmap == other_bitmap, - (Self::TextureRef(self_texture), Self::TextureRef(other_texture)) => { - self_texture.equals(*other_texture) - } - _ => false, - } - } -} - -impl From for ImageInputTexture<'_> { - fn from(b: BitmapHandle) -> Self { - ImageInputTexture::Bitmap(b) - } -} - -impl<'a> From<&'a dyn RawTexture> for ImageInputTexture<'a> { - fn from(t: &'a dyn RawTexture) -> Self { - ImageInputTexture::TextureRef(t) - } -} - #[derive(Debug, PartialEq, Clone)] pub struct PixelBenderShader { pub name: String, diff --git a/render/src/pixel_bender/tests.rs b/render/pixel_bender/src/tests.rs similarity index 99% rename from render/src/pixel_bender/tests.rs rename to render/pixel_bender/src/tests.rs index ff8f55daa860..eddceacd5f03 100644 --- a/render/src/pixel_bender/tests.rs +++ b/render/pixel_bender/src/tests.rs @@ -1,10 +1,10 @@ -use crate::pixel_bender::{ +use crate::parser::{ Opcode, Operation, PixelBenderMetadata, PixelBenderParam, PixelBenderParamQualifier, PixelBenderReg, PixelBenderRegChannel, PixelBenderRegKind, PixelBenderShader, PixelBenderType, PixelBenderTypeOpcode, }; -use super::parse_shader; +use super::parser::parse_shader; #[test] fn simple_shader() { diff --git a/render/src/backend.rs b/render/src/backend.rs index 637f8158e875..202993c70eeb 100644 --- a/render/src/backend.rs +++ b/render/src/backend.rs @@ -4,7 +4,8 @@ use crate::bitmap::{Bitmap, BitmapHandle, BitmapSource, PixelRegion, RgbaBufRead use crate::commands::CommandList; use crate::error::Error; use crate::filters::Filter; -use crate::pixel_bender::{PixelBenderShader, PixelBenderShaderArgument, PixelBenderShaderHandle}; +use crate::pixel_bender::{PixelBenderShader, PixelBenderShaderHandle}; +use crate::pixel_bender_support::PixelBenderShaderArgument; use crate::quality::StageQuality; use crate::shape_utils::DistilledShape; use ruffle_wstr::WStr; diff --git a/render/src/backend/null.rs b/render/src/backend/null.rs index 70b798925ac5..01123f5e540a 100644 --- a/render/src/backend/null.rs +++ b/render/src/backend/null.rs @@ -10,7 +10,8 @@ use crate::bitmap::{ }; use crate::commands::CommandList; use crate::error::Error; -use crate::pixel_bender::{PixelBenderShader, PixelBenderShaderArgument, PixelBenderShaderHandle}; +use crate::pixel_bender::{PixelBenderShader, PixelBenderShaderHandle}; +use crate::pixel_bender_support::PixelBenderShaderArgument; use crate::quality::StageQuality; use crate::shape_utils::DistilledShape; use swf::Color; diff --git a/render/src/filters.rs b/render/src/filters.rs index 6398b774b082..173f6098ac04 100644 --- a/render/src/filters.rs +++ b/render/src/filters.rs @@ -1,7 +1,6 @@ -use crate::{ - bitmap::BitmapHandle, - pixel_bender::{PixelBenderShaderArgument, PixelBenderShaderHandle}, -}; +use crate::bitmap::BitmapHandle; +use crate::pixel_bender::PixelBenderShaderHandle; +use crate::pixel_bender_support::PixelBenderShaderArgument; use std::{any::Any, fmt::Debug}; use swf::{Color, Rectangle, Twips}; diff --git a/render/src/lib.rs b/render/src/lib.rs index 2e0ea1d41ce4..c3d53d2d3747 100644 --- a/render/src/lib.rs +++ b/render/src/lib.rs @@ -10,7 +10,7 @@ pub mod lines; pub mod matrix; pub mod matrix3d; pub mod perspective_projection; -pub mod pixel_bender; +pub mod pixel_bender_support; // The `renderdoc` crate doesn't compile on apple platforms #[cfg(all(feature = "renderdoc", not(target_vendor = "apple")))] pub mod renderdoc; @@ -23,3 +23,5 @@ pub mod commands; pub mod quality; #[cfg(feature = "tessellator")] pub mod tessellator; + +pub use pixel_bender; diff --git a/render/src/pixel_bender_support.rs b/render/src/pixel_bender_support.rs new file mode 100644 index 000000000000..6b4e14c27ab3 --- /dev/null +++ b/render/src/pixel_bender_support.rs @@ -0,0 +1,58 @@ +use crate::backend::RawTexture; +use crate::bitmap::BitmapHandle; +use crate::pixel_bender::PixelBenderType; + +#[derive(Debug, Clone, PartialEq)] +pub enum PixelBenderShaderArgument<'a> { + ImageInput { + index: u8, + channels: u8, + name: String, + texture: Option>, + }, + ValueInput { + index: u8, + value: PixelBenderType, + }, +} + +/// An image input. +/// +/// This accepts both an owned BitmapHandle, and a borrowed texture +/// (used when applying a filter to a texture that we don't have +/// ownership of, and therefore cannot construct a BitmapHandle for). +#[derive(Debug, Clone)] +pub enum ImageInputTexture<'a> { + Bitmap(BitmapHandle), + TextureRef(&'a dyn RawTexture), + Bytes { + width: u32, + height: u32, + channels: u32, + bytes: Vec, + }, +} + +impl PartialEq for ImageInputTexture<'_> { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Bitmap(self_bitmap), Self::Bitmap(other_bitmap)) => self_bitmap == other_bitmap, + (Self::TextureRef(self_texture), Self::TextureRef(other_texture)) => { + self_texture.equals(*other_texture) + } + _ => false, + } + } +} + +impl From for ImageInputTexture<'_> { + fn from(b: BitmapHandle) -> Self { + ImageInputTexture::Bitmap(b) + } +} + +impl<'a> From<&'a dyn RawTexture> for ImageInputTexture<'a> { + fn from(t: &'a dyn RawTexture) -> Self { + ImageInputTexture::TextureRef(t) + } +} diff --git a/render/webgl/src/lib.rs b/render/webgl/src/lib.rs index a4a6f3fb6809..82ad96dc73f9 100644 --- a/render/webgl/src/lib.rs +++ b/render/webgl/src/lib.rs @@ -1217,7 +1217,7 @@ impl RenderBackend for WebGlRenderBackend { fn run_pixelbender_shader( &mut self, _handle: ruffle_render::pixel_bender::PixelBenderShaderHandle, - _arguments: &[ruffle_render::pixel_bender::PixelBenderShaderArgument], + _arguments: &[ruffle_render::pixel_bender_support::PixelBenderShaderArgument], _target: &PixelBenderTarget, ) -> Result { Err(BitmapError::Unimplemented("run_pixelbender_shader".into())) diff --git a/render/wgpu/src/backend.rs b/render/wgpu/src/backend.rs index c54ad35ea496..c2a341d3664b 100644 --- a/render/wgpu/src/backend.rs +++ b/render/wgpu/src/backend.rs @@ -24,9 +24,8 @@ use ruffle_render::bitmap::{ use ruffle_render::commands::CommandList; use ruffle_render::error::Error as BitmapError; use ruffle_render::filters::Filter; -use ruffle_render::pixel_bender::{ - PixelBenderShader, PixelBenderShaderArgument, PixelBenderShaderHandle, -}; +use ruffle_render::pixel_bender::{PixelBenderShader, PixelBenderShaderHandle}; +use ruffle_render::pixel_bender_support::PixelBenderShaderArgument; use ruffle_render::quality::StageQuality; use ruffle_render::shape_utils::DistilledShape; use ruffle_render::tessellator::ShapeTessellator; diff --git a/render/wgpu/src/filters/shader.rs b/render/wgpu/src/filters/shader.rs index 72ce69ac959c..0d79b5353fb4 100644 --- a/render/wgpu/src/filters/shader.rs +++ b/render/wgpu/src/filters/shader.rs @@ -1,6 +1,6 @@ use ruffle_render::{ filters::ShaderFilter as ShaderFilterArgs, - pixel_bender::{ImageInputTexture, PixelBenderShaderArgument}, + pixel_bender_support::{ImageInputTexture, PixelBenderShaderArgument}, }; use crate::{ diff --git a/render/wgpu/src/pixel_bender.rs b/render/wgpu/src/pixel_bender.rs index c324f7e51f95..f2e8235eaf0c 100644 --- a/render/wgpu/src/pixel_bender.rs +++ b/render/wgpu/src/pixel_bender.rs @@ -5,15 +5,13 @@ use std::num::NonZeroU64; use std::{borrow::Cow, cell::Cell, sync::Arc}; use indexmap::IndexMap; +use ruffle_render::bitmap::BitmapHandle; use ruffle_render::error::Error as BitmapError; use ruffle_render::pixel_bender::{ - ImageInputTexture, PixelBenderShaderHandle, PixelBenderShaderImpl, PixelBenderType, - OUT_COORD_NAME, -}; -use ruffle_render::{ - bitmap::BitmapHandle, - pixel_bender::{PixelBenderParam, PixelBenderShader, PixelBenderShaderArgument}, + PixelBenderParam, PixelBenderShader, PixelBenderShaderHandle, PixelBenderShaderImpl, + PixelBenderType, OUT_COORD_NAME, }; +use ruffle_render::pixel_bender_support::{ImageInputTexture, PixelBenderShaderArgument}; use smallvec::{smallvec_inline, SmallVec}; use wgpu::util::{DeviceExt, StagingBelt}; use wgpu::{ diff --git a/render/wgpu/src/surface.rs b/render/wgpu/src/surface.rs index 69b615d87755..5cd52cb7ba09 100644 --- a/render/wgpu/src/surface.rs +++ b/render/wgpu/src/surface.rs @@ -12,7 +12,7 @@ use crate::surface::commands::{chunk_blends, Chunk, CommandRenderer}; use crate::utils::{remove_srgb, supported_sample_count}; use crate::{Descriptors, MaskState, Pipelines}; use ruffle_render::commands::CommandList; -use ruffle_render::pixel_bender::{ImageInputTexture, PixelBenderShaderArgument}; +use ruffle_render::pixel_bender_support::{ImageInputTexture, PixelBenderShaderArgument}; use ruffle_render::quality::StageQuality; use std::sync::Arc; use target::CommandTarget;