Skip to content

avm2: Fix stack trace for context3DCreated event handler#23745

Merged
kjarosh merged 2 commits into
ruffle-rs:masterfrom
Lord-McSweeney:avm2-fix-context3d-stack
May 22, 2026
Merged

avm2: Fix stack trace for context3DCreated event handler#23745
kjarosh merged 2 commits into
ruffle-rs:masterfrom
Lord-McSweeney:avm2-fix-context3d-stack

Conversation

@Lord-McSweeney

@Lord-McSweeney Lord-McSweeney commented May 18, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR fixes the stack trace for the context3DCreated event handler. Previously, the event was manually dispatched from AS with a delay. Now, we set some state on the Stage3DObject, which is updated by code in the Stage display object at the beginning of the AVM2 frame lifecycle.

With the previous approach, the stack trace for the failing test avm2/stage3d_agal_upload_errors would have to be updated every time the total function count changed in our playerglobals.

Testing

I've marked the avm2/stage3d_agal_upload_errors test as passing and added a new test, avm2/context3d_creation.

Checklist

  • I, a human, have self-reviewed this PR and fully understand the changes within.
  • I have made or updated tests where possible.
  • All of my commits are properly scoped, compile successfully, and pass all tests.
  • This PR does not make sense to split up into smaller PRs.
  • An LLM was involved in the authoring of this code.

@Lord-McSweeney Lord-McSweeney added A-avm2 Area: AVM2 (ActionScript 3) T-compat Type: Compatibility with Flash Player labels May 18, 2026
@Lord-McSweeney
Lord-McSweeney force-pushed the avm2-fix-context3d-stack branch 2 times, most recently from 38edc3c to 8f09f78 Compare May 18, 2026 23:51
@Lord-McSweeney Lord-McSweeney added the waiting-on-review Waiting on review from a Ruffle team member label May 18, 2026
@kjarosh kjarosh removed the waiting-on-review Waiting on review from a Ruffle team member label May 22, 2026
@kjarosh
kjarosh force-pushed the avm2-fix-context3d-stack branch from 8f09f78 to e61afca Compare May 22, 2026 19:06
@kjarosh
kjarosh enabled auto-merge (rebase) May 22, 2026 19:06
Previously, the asynchronicity of context3d creation was implemented entirely
in AS using setTimeout. This added extra methods to the stack trace.
Asynchronicity for context3D creation is now handled entirely in Rust.
This removes extra methods from the stack trace from inside the event handler.
@Lord-McSweeney
Lord-McSweeney force-pushed the avm2-fix-context3d-stack branch from e61afca to b1916d0 Compare May 22, 2026 19:14
@kjarosh
kjarosh merged commit b95f757 into ruffle-rs:master May 22, 2026
26 checks passed
Hancock33 added a commit to Hancock33/batocera.piboy that referenced this pull request May 23, 2026
-----------------------------------------------------------------------------------
cemu.mk ca15637b6378a2c8424a4be8919aabb8c87992ce # Version: Commits on May 22, 2026
-----------------------------------------------------------------------------------
UI: Fix formatting error in TextureRelationWindow (#1926),

------------------------------------------------------------------------------------------
duckstation.mk fc72f17a5ceb0fe5d453789b6b5775fc5ff1c99c # Version: Commits on May 23, 2026
------------------------------------------------------------------------------------------
CI: Drop unused input (#3743)

actions/upload-artifact ignores the name input when using `archive: false`,

-----------------------------------------------------------------------------------
eden.mk 83683440b24c2d07536fddf2faa77c000c14374b # Version: Commits on May 22, 2026
-----------------------------------------------------------------------------------
[net] ban api.epicgames.dev domain (#3999)

--------------------------------------------------------------------------------------
flycast.mk bb304918f8d9f1d2c1e80ccabfa86806ef70bcfa # Version: Commits on May 22, 2026
--------------------------------------------------------------------------------------
Fetch translations & Recreate libretro_core_options_intl.h,

-----------------------------------------------------------------------------------
play.mk ba4c1f4d59a363819237574c1edfbfe53705072f # Version: Commits on May 20, 2026
-----------------------------------------------------------------------------------
Android: Replace migration logic with import/export logic.,

-----------------------------------------------------
ryujinx.mk 1.3.299 # Version: Commits on May 22, 2026
-----------------------------------------------------
1.3.299

---------------------------------------------------------------------------------------
touchhle.mk 40ab5aae95db6d909e31f0a202e6d19b35655680 # Version: Commits on Jul 26, 2025
---------------------------------------------------------------------------------------
CGImageCreate() for the case of XRGB in 32 little endian

Change-Id: Icad59ef03a562b89f1e6905da8837272c671abf8,

--------------------------------------------------------------------------------------
tsugaru.mk 286b6c057e19b68209ed8c64d8a82581816b0998 # Version: Commits on May 22, 2026
--------------------------------------------------------------------------------------
Cleaning,

-----------------------------------------------------------------------------------------
xenia-edge.mk 882cd7e9171a713a011f6ac0dd9c2bf6979eb4f7 # Version: Commits on May 23, 2026
-----------------------------------------------------------------------------------------
[App] Implement game library storage separate from dash GPD

Original implementation overloaded dash gpd for each profile in order to

store game library data, including launch paths, disc labels etc.

This created some hairy code to deal with various edge cases and still

allowed for unusual interactions to blow away a user's profile settings.

This moves that into separate storage in storage_root/library/ that

mirrors content/ in some sense and maintains per title data like launch

path, icon, and maybe artwork etc in the future, in a location that's

not fundamentally tied to profiles, making the code more straightfoward

and potential for corrupting profiles/library data greatly reduced if

not completely eliminated.,

---------------------------------------------------------------
ruffle.mk nightly-2026-05-23 # Version: Commits on May 23, 2026
---------------------------------------------------------------
## What's Changed

* chore: Bump eslint-plugin-jsdoc from 62.9.0 to 63.0.0 in /web by @dependabot[bot] in ruffle-rs/ruffle#23781

* chore: Bump the npm-minor group across 1 directory with 7 updates by @dependabot[bot] in ruffle-rs/ruffle#23779

* chore: Fix a bunch of typos (mostly in comments) by @torokati44 in ruffle-rs/ruffle#23782

* chore: Bump qs and express in /web by @dependabot[bot] in ruffle-rs/ruffle#23784

* avm2: Fix stack trace for context3DCreated event handler by @Lord-McSweeney in ruffle-rs/ruffle#23745

* avm2: Verify that lazy namespace is actually a Namespace in the verifier by @Lord-McSweeney in ruffle-rs/ruffle#23777

**Full Changelog**: ruffle-rs/ruffle@nightly-2026-05-22...nightly-2026-05-23,

---------------------------------------------------------------------------------------
thextech.mk 6bd0b7350bde280e24553091a63621aabf7e8dc6 # Version: Commits on May 22, 2026
---------------------------------------------------------------------------------------
Updated AudioCodecs and MixerX,

----------------------------------------------------------------------------------------------------
gamenetworkingsockets.mk b88a52c2065824d5425ecbba07881e57e16c0c16 # Version: Commits on May 23, 2026
----------------------------------------------------------------------------------------------------
Fix dangling pointer bug

If there is more than one STUN server and the name is

shorter than std::string small string optimization size.,

------------------------------------------------------------------------------------------------
libretro-mame-src.mk eaa63ea220874f70adce2e5afccd7509516fbf0a # Version: Commits on May 23, 2026
------------------------------------------------------------------------------------------------
Merge remote-tracking branch 'upstream/master',

----------------------------------------------------------------------------------------
retroarch.mk dc3cef4545ec3dd19887c18df5e01ac0478237c2 # Version: Commits on May 23, 2026
----------------------------------------------------------------------------------------
Fetch translations from Crowdin,

---------------------------------------------------------------------------------------
vpinball.mk bd65c64fe04b41f2ecfdb00ecdc6aef1eaf05706 # Version: Commits on May 22, 2026
---------------------------------------------------------------------------------------
pup: render ForcePop screens and keep labels on same-page show (#3429),

----------------------------------------------------------------------------------------
doomretro.mk 8e3a2551e8e4c186f739bf2a7fd13ae4aa45e0b7 # Version: Commits on May 23, 2026
----------------------------------------------------------------------------------------
Improvements to updating expansion

Fixes updating `expansion` CVAR during intermission causing next map to be opened from different expansion,

--------------------------------------------------------------------------------------
vkquake.mk b743a8fc024a98a2da2192225710e3443eed88f3 # Version: Commits on May 18, 2026
--------------------------------------------------------------------------------------
r_world.c : Split work again by a small factor (MARK_SURFACE_CALLS_PER_WORKER),

------------------------------------------------------------------------------------------
xash3d-fwgs.mk 25ca2ecb121810c0d3c241bd211cc9e64fa335fa # Version: Commits on May 22, 2026
------------------------------------------------------------------------------------------
engine: fix Netchan_Validate units bug allowing oversized fragments,

---------------------------------------------------------------------------------------------
libretro-fbneo.mk ebee599355682000d25eb041601c00f07fbeae10 # Version: Commits on May 23, 2026
---------------------------------------------------------------------------------------------
(libretro) update files,

-----------------------------------------------------------------------------------------------
libretro-flycast.mk bb304918f8d9f1d2c1e80ccabfa86806ef70bcfa # Version: Commits on May 22, 2026
-----------------------------------------------------------------------------------------------
Fetch translations & Recreate libretro_core_options_intl.h,

--------------------------------------------------------------------------------------------------
libretro-gearcoleco.mk 6a9a99f78e398e5d679773d9cf97e415e9526dc0 # Version: Commits on May 22, 2026
--------------------------------------------------------------------------------------------------
Align fullscreen feature implementation,

-------------------------------------------------------------------------------------------------
libretro-geargrafx.mk 87093ae372d5134a0bba2d759cb17d10262e0bcc # Version: Commits on May 23, 2026
-------------------------------------------------------------------------------------------------
Improve CD seek timing,

--------------------------------------------------------------------------------------------------
libretro-gearsystem.mk 0efba78ce74b6e1440734084627d3739dd2f99f3 # Version: Commits on May 22, 2026
--------------------------------------------------------------------------------------------------
Align fullscreen feature implementation,

-----------------------------------------------------------------------------------------------------
libretro-mame2003-plus.mk 0191984c9e92482f15536135de9baeff082be63e # Version: Commits on May 22, 2026
-----------------------------------------------------------------------------------------------------
Add support for 16KB pages on Android. (#2019),

----------------------------------------------------------------------------------------------
libretro-stella.mk a9affd080f2768942e7511b62030e72d27ab52b0 # Version: Commits on May 23, 2026
----------------------------------------------------------------------------------------------
And another TODO I missed.,
Hancock33 added a commit to Hancock33/batocera.piboy that referenced this pull request Jun 14, 2026
-----------------------------------------------------------------------------------
cemu.mk fe70fdcfe5ced5a4032b7c4561f7cad6f011314b # Version: Commits on Jun 13, 2026
-----------------------------------------------------------------------------------
debugger: Don't clear register views when continuing to run code,

------------------------------------------------------------------------------------------
duckstation.mk cfde5bf5c3418d3ae4be566dc21dca467da1c5b5 # Version: Commits on Jun 07, 2026
------------------------------------------------------------------------------------------
Achievements: Move achievement pinning to database,

--------------------------------------------------------------------------------------
openmsx.mk 3a40a511c97cbf42f86aa90394a4fe07ad455cd3 # Version: Commits on Jun 13, 2026
--------------------------------------------------------------------------------------
corrections and additions to the romdb,

----------------------------------------------------
pcsx2.mk v2.7.416 # Version: Commits on Jun 13, 2026
----------------------------------------------------
- [Misc: clean up COM code](PCSX2/pcsx2#14562)

,

-------------------------------------------------------------------------------------
ppsspp.mk 14dc5a51560628581c023235e9d35ec28fb14b6a # Version: Commits on Jun 14, 2026
-------------------------------------------------------------------------------------
Merge pull request #21825 from hrydgard/ridge-racer-sprite

Fix the ugly line on Ridge Racer lens flares,

------------------------------------------------------------------------------------
rpcs3.mk 4fed5e7b88d78c03359009377b740a3c826505a7 # Version: Commits on Jun 14, 2026
------------------------------------------------------------------------------------
Fix iso integrity log message,

-----------------------------------------------------------------------------------
ymir.mk bca07409fdd89d5e136356a063da71d9874d3424 # Version: Commits on Jun 13, 2026
-----------------------------------------------------------------------------------
feat(sys): Use GCD to ensure SH2 overclocking doesnt introduce slight clock errors to other components,

-------------------------------------------------------------------------------------
ikemen.mk c42967d13e5b229f7dcf9450f471fd2a15d5858f # Version: Commits on Jun 13, 2026
-------------------------------------------------------------------------------------
Merge pull request #3705 from SuperFromND/bgdef-modelrotate

feat: `modelrotate` for 3D BGDefs,

---------------------------------------------------
ruffle.mk v0.3.0 # Version: Commits on Jun 14, 2026
---------------------------------------------------
## What's Changed

* avm2: Fixes to Error's prototype by @Lord-McSweeney in ruffle-rs/ruffle#23719

* aur: Update maintainers for ruffle-nightly-bin by @kjarosh in ruffle-rs/ruffle#23727

* Add testutils CLI by @Dinnerbone in ruffle-rs/ruffle#23677

* ci: Use correct npm dist-tag for nightly and stable releases by @kjarosh in ruffle-rs/ruffle#23728

* desktop: Add Rust stack trace to panic reports by @kjarosh in ruffle-rs/ruffle#23714

* avm2: Fix new Video(0, 0) to use default size by @1bugproof in ruffle-rs/ruffle#23708

* avm2: Stop assuming Object is an enum by @SuchAFuriousDeath in ruffle-rs/ruffle#23725

* Enable jpegxr on Linux Nightlies by @Fancy2209 in ruffle-rs/ruffle#23741

* avm1: Fix behavior of `Sound` ownership by @ChrisCPI in ruffle-rs/ruffle#23733

* chore: Bump the npm-minor group in /web with 7 updates by @dependabot[bot] in ruffle-rs/ruffle#23748

* chore: Bump enumset to 1.1.13 by @torokati44 in ruffle-rs/ruffle#23753

* chore: Bump cssnano to 8.0.1 and cssnano-preset-advanced to 8.0.1 in /web by @torokati44 in ruffle-rs/ruffle#23752

* chore: Run `npm audit fix` in web/ by @torokati44 in ruffle-rs/ruffle#23742

* video/vp6: Init nihav decoder with encoded size, not display size by @SuchAFuriousDeath in ruffle-rs/ruffle#23665

* web/audio: Pin AudioContext to 44.1 kHz by @SuchAFuriousDeath in ruffle-rs/ruffle#23701

* web: Fix MVP wasm build by explicitly disabling post-MVP features by @SuchAFuriousDeath in ruffle-rs/ruffle#23756

* avm2: Set dobj as transformed_by_script on transform `colorTransform` and `matrix` setters by @ChrisCPI in ruffle-rs/ruffle#23759

* avm2: Return ArgumentError instead of panicking on invalid ShaderJob target by @SuchAFuriousDeath in ruffle-rs/ruffle#23763

* chore: Migrate to current Node.js 26 from 25 for testing by @torokati44 in ruffle-rs/ruffle#23661

* avm2: Print full error details when logging caught error by @Lord-McSweeney in ruffle-rs/ruffle#23726

* avm2: Remove mostly unused `crate::avm2::string` by @Lord-McSweeney in ruffle-rs/ruffle#23773

* wstr: Remove unsafe usage from str_eq by @kjarosh in ruffle-rs/ruffle#23774

* desktop: Remove fontconfig from Windows and add fontconfig-dlopen  by @kjarosh in ruffle-rs/ruffle#23768

* chore: Bump nihav-vp6 to latest git master by @torokati44 in ruffle-rs/ruffle#23765

* chore: Bump eslint-plugin-jsdoc from 62.9.0 to 63.0.0 in /web by @dependabot[bot] in ruffle-rs/ruffle#23781

* chore: Bump the npm-minor group across 1 directory with 7 updates by @dependabot[bot] in ruffle-rs/ruffle#23779

* chore: Fix a bunch of typos (mostly in comments) by @torokati44 in ruffle-rs/ruffle#23782

* chore: Bump qs and express in /web by @dependabot[bot] in ruffle-rs/ruffle#23784

* avm2: Fix stack trace for context3DCreated event handler by @Lord-McSweeney in ruffle-rs/ruffle#23745

* avm2: Verify that lazy namespace is actually a Namespace in the verifier by @Lord-McSweeney in ruffle-rs/ruffle#23777

* tests: Begin adding test coverage for signatures of flash.events classes by @Lord-McSweeney in ruffle-rs/ruffle#23786

* ci: Generate AVM2 report only for nightlies by @kjarosh in ruffle-rs/ruffle#23787

* avm1: Clear stack only between frames by @kjarosh in ruffle-rs/ruffle#23795

* avm1: Introduce AVM1 playerglobal by @Dinnerbone in ruffle-rs/ruffle#23730

* core: Fix movie clip looping by @kjarosh in ruffle-rs/ruffle#23802

* tests: Add --skip-no-player to testutils execute by @kjarosh in ruffle-rs/ruffle#23805

* tests: Trace warnings if enabled when executing tests by @kjarosh in ruffle-rs/ruffle#23804

* avm1: Do not trace an error on with(undefined)/with(null) by @kjarosh in ruffle-rs/ruffle#23809

* core: Normalize \blank\ target to \_blank\ in getURL/navigateToURL  by @SuchAFuriousDeath in ruffle-rs/ruffle#23792

* avm1: Remove magic properties and this from SWF4 by @kjarosh in ruffle-rs/ruffle#23806

* avm2: Implement a number of missing `flash.events` classes by @Lord-McSweeney in ruffle-rs/ruffle#23812

* tests: Use FP's output in avm2/graphics_draw_triangles by @kjarosh in ruffle-rs/ruffle#23818

* chore: Bump josStorer/get-current-time from 2.1.2 to 2.1.3 by @dependabot[bot] in ruffle-rs/ruffle#23820

* chore: Bump the npm-minor group in /web with 2 updates by @dependabot[bot] in ruffle-rs/ruffle#23822

* chore: Bump the cargo-minor group with 3 updates by @dependabot[bot] in ruffle-rs/ruffle#23823

* chore: Bump webdriverio package family to 9.27.2 in web/ by @torokati44 in ruffle-rs/ruffle#23828

* avm2: More fixes to signatures of `flash.events` classes by @Lord-McSweeney in ruffle-rs/ruffle#23833

* avm1: Support property syntax in delete2 by @kjarosh in ruffle-rs/ruffle#23834

* 🤖 core: Move flash.text.engine TextLine onto its own DisplayObject by @doctorpangloss in ruffle-rs/ruffle#23817

* core: Extract run_file_dialog helper to reduce boilerplate in file dialog loaders by @SuchAFuriousDeath in ruffle-rs/ruffle#23831

* core/render: Add support for loading JPEGXR images by @ChrisCPI in ruffle-rs/ruffle#23789

* tests: Add asc compiler for compiling AVM2 tests by @kjarosh in ruffle-rs/ruffle#23794

* chore: Bump tmp from 0.2.5 to 0.2.7 in /web by @dependabot[bot] in ruffle-rs/ruffle#23843

* refactor: Enum-map related improvements by @SuchAFuriousDeath in ruffle-rs/ruffle#23846

* wgpu: Yeet the copy_srgb shader and pipeline by @SuchAFuriousDeath in ruffle-rs/ruffle#23827

* tests: Add a failing visual test for scale_rotation_cache by @torokati44 in ruffle-rs/ruffle#23796

* avm2: Minor performance improvements by @Lord-McSweeney in ruffle-rs/ruffle#23840

* core: Include `ruffle_render/jpegxr` in `jpegxr` feature by @ChrisCPI in ruffle-rs/ruffle#23852

* chore: Clippy beta fixes by @danielhjacobs in ruffle-rs/ruffle#23762

* ci: Enable fontconfig-dlopen in the macOS Rust tester job by @torokati44 in ruffle-rs/ruffle#23855

* core: Make loaded image MovieClips work the way SWF >= 5 movies do wrt. scale and rotation caching by @torokati44 in ruffle-rs/ruffle#23838

* avm2: Refactor draw_triangles_internal by @SuchAFuriousDeath in ruffle-rs/ruffle#23761

* core: Rework infrastructure around the FileDialogResult trait by @SuchAFuriousDeath in ruffle-rs/ruffle#23844

* text: Prevent measuring text twice during layout by @kjarosh in ruffle-rs/ruffle#23862

* core: Simplify code in MovieClip.event_dispatch by @kjarosh in ruffle-rs/ruffle#23867

* swf: Add support for PlaceObject/allEventFlags by @kjarosh in ruffle-rs/ruffle#23868

* wstr: Implement Pattern for owned [u8; N] and [u16; N] arrays by @SuchAFuriousDeath in ruffle-rs/ruffle#23858

* ci: Don't enable fontconfig-dlopen in the macOS Rust tester job by @torokati44 in ruffle-rs/ruffle#23873

* ci: Enable full LTO for releases by @kjarosh in ruffle-rs/ruffle#23863

* web: Polyfill document.embeds to return ruffle-embeds too by @danielhjacobs in ruffle-rs/ruffle#22449

* web: Support named access on document.embeds by @danielhjacobs in ruffle-rs/ruffle#23878

* core: Add MultiFileDialogResult and display_file_open_dialog_multiple by @SuchAFuriousDeath in ruffle-rs/ruffle#23866

* avm2: Add type enum for error 2006 by @ChrisCPI in ruffle-rs/ruffle#23883

* chore: Bump the npm-minor group in /web with 11 updates by @dependabot[bot] in ruffle-rs/ruffle#23885

* chore: Bump zbus, zvariant, toml crates by @torokati44 in ruffle-rs/ruffle#23887

* chore: Bump the cargo-minor group across 1 directory with 6 updates by @dependabot[bot] in ruffle-rs/ruffle#23886

* chore: Cargo.lock maintenance by @torokati44 in ruffle-rs/ruffle#23888

* core: Do not dispatch clip events not present in allEventFlags by @kjarosh in ruffle-rs/ruffle#23869

* Fix panic on writeback from empty CPU dirty region (prevalent in Earn to Die) by @n-raine in ruffle-rs/ruffle#23898

* avm2: Implement most of the version gating for `flash.events` classes by @Lord-McSweeney in ruffle-rs/ruffle#23836

* avm2: More minor crossbridge performance improvements by @Lord-McSweeney in ruffle-rs/ruffle#23849

* tests: add `known_failure` support to audio assertions by @moulins in ruffle-rs/ruffle#23861

* avm2: Fix setProgramConstantsFromByteArray implementation by @SuchAFuriousDeath in ruffle-rs/ruffle#23901

* frontend-utils: Use native TLS instead of rustls by @kjarosh in ruffle-rs/ruffle#23894

* chore: Bump openssl from 0.10.73 to 0.10.80 by @dependabot[bot] in ruffle-rs/ruffle#23902

* chore: Additional Rust dependency version bumps by @torokati44 in ruffle-rs/ruffle#23903

* avm1: Match Flash broadcaster prototype enumeration order by @SuchAFuriousDeath in ruffle-rs/ruffle#23892

* avm1: Stub several classes and properties by @SuchAFuriousDeath in ruffle-rs/ruffle#23899

* avm1: Define `constructor` as own property on system class objects by @SuchAFuriousDeath in ruffle-rs/ruffle#23893

* avm2: Add a field to ops instead of adding separate integral variants by @Lord-McSweeney in ruffle-rs/ruffle#23923

* chore: Bump the npm-minor group in /web with 6 updates by @dependabot[bot] in ruffle-rs/ruffle#23925

* avm1: Xmlsocket connect null fix by @SuchAFuriousDeath in ruffle-rs/ruffle#23931

* Slice logic cleanup, take 2 by @moulins in ruffle-rs/ruffle#23676

* core: Make use of  `istr!` macro in several places by @SuchAFuriousDeath in ruffle-rs/ruffle#23935

* core: Remove unnecessary `dyn` usage by @SuchAFuriousDeath in ruffle-rs/ruffle#23936

* core: Use __jcvt() intrinsic on AArch64 for f64→i32 conversion by @SuchAFuriousDeath in ruffle-rs/ruffle#23937

* chore: Bump shell-quote from 1.8.3 to 1.8.4 in /web by @dependabot[bot] in ruffle-rs/ruffle#23941

* frontend-utils: Allow switching reqwest back to rustls by @torokati44 in ruffle-rs/ruffle#23947

* avm1: Remove \Target not found\ trace by @kjarosh in ruffle-rs/ruffle#23946

* avm2: Fix serializing invalid Date objects by @Lord-McSweeney in ruffle-rs/ruffle#23951

* swf: Seek to glyph shape offsets when reading DefineFont2/3 by @kjarosh in ruffle-rs/ruffle#23949

* + libssl-dev, openssl-devel by @sombraguerrero in ruffle-rs/ruffle#23953

* avm1: Support SWF4 target paths properly by @kjarosh in ruffle-rs/ruffle#23948

* chore: Bump WebdriverIO to 9.28.0 in web/ by @torokati44 in ruffle-rs/ruffle#23954

* swf: Fix underflow on keyPress clip action without key code by @kjarosh in ruffle-rs/ruffle#23958

* swf: Fix overflow while reading convolution filter by @kjarosh in ruffle-rs/ruffle#23961

* swf: Fix underflow/OOM errors when decompressing by @kjarosh in ruffle-rs/ruffle#23962

* core: Add AvmString::split_dependent by @SuchAFuriousDeath in ruffle-rs/ruffle#23955

* swf: Fix potential OOM in DefineSceneAndFrameLabelData by @kjarosh in ruffle-rs/ruffle#23960

* avm1: Fix SetTarget2 movie clip selection by @kjarosh in ruffle-rs/ruffle#23964

* chore: Update translations from Crowdin by @kjarosh in ruffle-rs/ruffle#23967

* avm1: Handle edge values in setProperty() by @kjarosh in ruffle-rs/ruffle#23966

* avm2: Simplify AMF serialization logic by @Lord-McSweeney in ruffle-rs/ruffle#23956

* avm2: Remove redundant method `PropertyMap::insert_with_namespace` by @Lord-McSweeney in ruffle-rs/ruffle#23969

* chore: Bump esbuild from 0.28.0 to 0.28.1 in /web by @dependabot[bot] in ruffle-rs/ruffle#23968

* chore: Update translations from Crowdin by @kjarosh in ruffle-rs/ruffle#23970

* refactor: Use api-report as dependency and move stub-report to tools/ by @kjarosh in ruffle-rs/ruffle#23922

* avm1/avm2: Add AMF NetConnection Array serialization known failures by @danielhjacobs in ruffle-rs/ruffle#23957

* tests: Add avm1/set_target_2_swf5 test by @kjarosh in ruffle-rs/ruffle#23965

## New Contributors

* @doctorpangloss made their first contribution in ruffle-rs/ruffle#23817

**Full Changelog**: ruffle-rs/ruffle@v0.2.0...v0.3.0,

---------------------------------------------------------------------------------------
thextech.mk db3a01db31435fc4524bb42ab81d99b3f6aa0807 # Version: Commits on Jun 14, 2026
---------------------------------------------------------------------------------------
changelog.txt: move MDX to 1.3.7.3 changelog,

-------------------------------------------------------------------------------------------
jazz2-native.mk a09fd6b6e54c42c9e5c622704b14a6ae32e06d1c # Version: Commits on Jun 13, 2026
-------------------------------------------------------------------------------------------
Tilemap draw call aggregation, improved player color customization,

-----------------------------------------------------
ledspicer.mk 0.7.6 # Version: Commits on Jun 14, 2026
-----------------------------------------------------
LEDSpicer v0.7.6 - Release Notes

Release Date

June 14, 2026

Overview

This release focuses on critical stability improvements and bug fixes for crafted profile handling and memory management.

� Bug Fixes

Crafted Profile System

    Fixed use-after-free crash when loading the same crafted profile twice

    Improved profile caching - Crafted profiles are now properly cached by game name instead of being rebuilt on every request

    Fixed profile stack history - FinishLastProfile now correctly steps back one profile at a time through the history stack

Flag Handling

    Corrected FORCE_RELOAD flag - Profile reload now properly ignores cache and rebuilds in place

    Corrected REPLACE flag - Profile replacement logic now works correctly on the craft/load path

� Changes

Configuration Updates

    Configuration values now use proper boolean capitalization (True/False instead of true/false)

    Enhanced configuration defaults in ledspicer.conf

Code Quality

    Refactored profile management to eliminate redundant cache operations

    Improved memory management with proper reference counting for replaced profiles

    Enhanced logging for better debugging of profile lifecycle

Documentation & Branding

    Updated README with improved project description and branding

    Enhanced feature list and typical use cases documentation

    Updated copyright year to 2026

CI/CD

    Updated GitHub Actions checkout action from v4 to v6

Package Updates

    Updated version across all package managers (Debian, RPM, Arch)

🔧 Technical Details

    Changed default platform parameter handling in craftProfile()

    Introduced replaceProfileReferences() for cleaner memory management

    Optimized cache key handling for platform templates vs. crafted profiles

----------------------------------------------------------------------------------------
retroarch.mk 2669eaad7b4318c415028e3d2feaf9d7f092885e # Version: Commits on Jun 14, 2026
----------------------------------------------------------------------------------------
Fetch translations from Crowdin,

----------------------------------------------------------------------------------------
doomretro.mk e011e4abf085fbbf5d7c9ba862bab40f48543bed # Version: Commits on Jun 14, 2026
----------------------------------------------------------------------------------------
Fix double use of uppercase(),

--------------------------------------------------------------------------------------
yquake2.mk dcda9144d34a5d76ff462675ff05d8acde30ecfe # Version: Commits on Jun 13, 2026
--------------------------------------------------------------------------------------
models: fix MDR uncompressed-frame heap overflow from byte/float count mix-up,

------------------------------------------------------------------------------------------
xash3d-fwgs.mk 1e31fbcd513bdabd557a098fcdd06fa2037cd99e # Version: Commits on Jun 14, 2026
------------------------------------------------------------------------------------------
ref: shut up DecalShoot about decals must hit mod_brush

This is an annoying message that's caused by the game code. Decals, without

custom renderer, cannot be rendered on non-brush entities, and everybody knows

that anyway.,

-------------------------------------------------------------------------------------------------------
libretro-beetle-pce-fast.mk 718dd0abb9ffcd95308ae79594e86d15148d7a2f # Version: Commits on Jun 14, 2026
-------------------------------------------------------------------------------------------------------
libretro: add zero-copy software-framebuffer direct render path

Use RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER so the VDC can

render straight into the frontend's (often GPU-mapped) framebuffer,

removing the surface->frontend copy that video_cb otherwise performs.

The renderer already writes through a single MDFN_Surface target whose

pixels/pitch it dereferences at render time (target = surface->pixels +

(frame_counter-14)*surface->pitch, all Mix*/Draw* honour surface->pitch),

so the direct path needs no renderer changes: in retro_run, before

Emulate, request a framebuffer; if granted, repoint surf->pixels/pitch at

it for the frame, render, ship video_cb from there with the framebuffer's

pitch, then restore the persistent fallback surface.

Why this is safe:

- The VDC renderer is write-only on the target surface (verified: every

  reference is a store), so an uncached framebuffer (no

  RETRO_MEMORY_TYPE_CACHED) is fine; access_flags is WRITE only.

- We do NOT rely on persistent buffer contents: for every scanline in the

  shipped rect [DisplayRect.y, +h) the renderer writes the whole line

  (Mix + DrawOverscan sides, or a full DrawOverscan in burst/blank), so a

  frontend that rotates buffers per frame yields no garbage.

- Only used when the granted buffer is RGB565 (our native output), large

  enough (>= FB_WIDTH x FB_HEIGHT), and has an even byte pitch; otherwise

  the calloc'd fallback surface is used unchanged.

- Frameskip frames don't request a buffer (video_cb(NULL,...) as before).

- If the frontend doesn't implement the call, the result is latched off

  (fb_direct_supported) so we probe only once.

surf->pixels/pitch are always restored after the frame, so the fallback

surface is intact whenever a frame declines the framebuffer. Pitch is

taken from the framebuffer (bytes -> uint16), not assumed to be FB_WIDTH.

(The old psp_hw_render branch rendered its SW path into its own surface

and used the PSP GU for HW; it predates this env call, so there was no

code to port - only the confirmation that the renderer funnels through

one retargetable surface pointer, which makes this drop-in.)

Verified: full clean build (make -j4, exit 0, .so, 0 warnings); libretro.c

passes -std=gnu89 -Werror=declaration-after-statement.,

--------------------------------------------------------------------------------------------------
libretro-beetle-psx.mk d460f8342060526678e7fd8222048324c2a80d86 # Version: Commits on Jun 14, 2026
--------------------------------------------------------------------------------------------------
gpu: SSE2-direct Gouraud RGB lane build in DrawSpanVec_NT (no stack roundtrip)

Replaces the scalar-loop-then-_mm_loadu_si128 Gouraud channel build with

direct SSE2 lane construction.  The original

    for (l = 0; l < step; l++) {

        R8[l] = (uint16_t)CHAN(cr, dr, l);

        G8[l] = (uint16_t)CHAN(cg, dg, l);

        B8[l] = (uint16_t)CHAN(cb, db, l);

    }

    R = _mm_loadu_si128((const __m128i*)R8);  /* + G, B */

lowered under gcc 13 -O3 to per-lane leal (cr + dr*l) into GPRs, store

to stack at R8[l], movd back to xmm, punpck-chains.  This shape was the

dominant spill source in the GOURAUD-on (G1) non-textured (T0) hot

loops -- in the unpatched gpu.s, the .L31928 family contained loops

with 97-116 xmm operations and 38-39 stack writes each, across every

T0 + (BMopaque | BMavg | BMaddq | BMadd) blend specialization.

The contributing mechanism: the per-lane GPR live ranges produced by

the scalar loop straddle the dense SIMD blend body that follows, so

the register allocator chooses to materialize each lane's GPR result

on the stack before reloading into xmm.  Replacing the loop with

straight SSE2 ops (vbase broadcast + step vectors + paddd + psrld +

packssdw) keeps the channel intermediates xmm-resident across the

entire blend body.

Approach: lane l holds ((base + d*l) >> 24).  d2..d7 are produced via

paired adds (cheaper than the imuls gcc would pick for d * l, and the

32-bit lanes have plenty of headroom -- worst-case dr*7 has fewer than

25 bits given the Gouraud range).  After the >> 24 shift each lane is

<= 255, so the final packs_epi32 down to u16x8 cannot saturate.

setr_epi32 calls fold to a single mov-from-rodata when dr/dg/db are

constant per span (the common case at the polygon level), and to a

small insert chain otherwise.

Spill counts (gcc 13.3, -O3, x86_64):

  function                                          before     after

  G_Command_DrawPolygon_NV4_G1_T0_BMopaque*         spills=39  spills=0

  G_Command_DrawPolygon_NV4_G1_T0_BMavg*            spills=39  spills=0

  G_Command_DrawPolygon_NV4_G1_T0_BMaddq*           spills=39  spills=0

  G_Command_DrawPolygon_NV4_G1_T0_BMadd*            spills=39  spills=0

  G_Command_DrawPolygon_NV4_G1_T0_BMsub*            spills=39  spills=0

The remaining spill leaders shift to the T1 (textured) variants at

xmm=16 spills=28-30; those follow the same scalar-then-pack pattern

on UV coordinates and are a separate follow-up.

End-to-end bench (x86_64 Linux, gcc 13.3, full DrawSpanVec_NT

BMopaque path -- Gouraud build + dither-off + pack RGB565 + bg load +

write-back, 100000 spans x 320 pixels):

  -O3:  21.0 -> 14.8 ms   (1.42x)   1520 -> 2165 Mpix/s

  -O2:  21.9 -> 15.8 ms   (1.39x)   1455 -> 2028 Mpix/s

Bit-exact across 500000 random Gouraud lane verifications (dr range

10..24 bits, both step=4 and step=8, plus edge cases at dr=0 and

dr=0xFFFFFFFF) and 200 random spans rendered into VRAM.

The NEON / scalar path is unchanged.  On NEON, the original

`vld1q_u16(R8)` plus per-lane access via vget_lane_u8 lowers to direct

register extracts without the stack roundtrip the SSE2 path saw, so

the same gcc lowering bug doesn't apply.  ARMv7 NEON specifically may

need its own audit but the codegen on AArch64 doesn't show comparable

spill density.,

----------------------------------------------------------------------------------------------
libretro-fake08.mk 814991a2571ad3970e386cef48f3b148aa1c27b9 # Version: Commits on Jun 13, 2026
----------------------------------------------------------------------------------------------
Merge pull request #267 from ysamlan/fix-vibrato-modulation

Fix vibrato effect: correct sawtooth to triangle wave modulation,

------------------------------------------------------------------------------------------------
libretro-gambatte.mk e99e1bd9b91de67ac12c77c3679c85447c26e8c8 # Version: Commits on Jun 14, 2026
------------------------------------------------------------------------------------------------
ppu: extend BG palette expansion to the CGB fast path

Follow-up to a991736 (\ppu: precomputed BG palette expansion for DMG

fast path\).  That commit treated only doFullTilesUnrolledDmg; the

CGB renderer at doFullTilesUnrolledCgb had the same eight-dependent-

load gather shape but with per-tile palette selection driven by the

attribute byte (bgPalette + (nattrib & 7) * 4) and was deferred

pending an L1-pressure measurement against the [8][256][4] table.

Microbench result: the working set was a non-issue.  Even with all 8

palettes cycling per tile (worst case -- every attribute byte

different), the 32 KiB total table is L1-friendly because the access

pattern (16 bytes per palette per tile) hits the same line repeatedly

within a tile.  Typical CGB scenes use only a few palettes per frame,

making the hot working set much smaller than the full table.

Microbench (full do-while incl. ntileword and nattrib recompute,

5000 frames x 144 lines x 20 tiles, x86_64 gcc 13.3 -O3):

  Scenario A: 1 palette used (typical):

    old: 53.0 ms (272 Mtiles/s) -> new: 27.5 ms (523 Mtiles/s)  1.93x

  Scenario B: 8 palettes cycling (worst-case for L1):

    old: 53.0 ms (272 Mtiles/s) -> new: 27.2 ms (529 Mtiles/s)  1.95x

Bit-exact across 50000 random trials.

Implementation:

  - bgPaletteExpanded changes shape from [256][4] to [8][256][4].

    Size goes from 4 KiB to 32 KiB (u32 build) / from 2 KiB to 16 KiB

    (VIDEO_RGB565 / VIDEO_ABGR1555 build).  The DMG renderer indexes

    the [0] slot; the CGB renderer indexes [nattrib & 7].

  - refreshBgPaletteExpansion gains a unsigned palette_id argument.

    DMG-mode callers pass 0; the CGB hooks pass the slot affected by

    the BCPD write (index >> 3).  Refreshing one palette costs 256

    iterations of the 4-lane inner expansion -- about 1024 stores --

    so per-palette refresh keeps writes proportional to the work the

    palette change actually invalidated.

  - refreshPalettes (the bulk-reload path used by loadState,

    swapToDMG, the colour-correction setters) rebuilds all 8 slots in

    CGB mode and just slot 0 in DMG mode.  doCgbBgColorChange (the

    one-entry-at-a-time BCPD path) rebuilds the affected slot.

    dmgBgPaletteChange (BGP register) rebuilds slot 0.  These are

    the only paths that write ppu.bgPalette in the codebase.

Codegen (gcc 13.3 -O3, x86_64): both inner loops now have the same

shape -- the do-while body lowers to four movdqu pairs per unrolled

iteration (gcc unrolls by 2, processing 16 pixels per loop body),

plus the nattrib/ntileword recompute scalar tail.

The CGB path's 32 KiB worst case is still smaller than every modern

L1d (x86 32-48 KiB, ARM Cortex-A53/A72 32 KiB), and the typical hot

working set is one or two 4 KiB slots.,

--------------------------------------------------------------------------------------------------
libretro-gearcoleco.mk e6c987725eb2ac6dc0edc85b0dea30fdc7e938d7 # Version: Commits on Jun 14, 2026
--------------------------------------------------------------------------------------------------
Update readme,

-------------------------------------------------------------------------------------------------
libretro-geargrafx.mk 31e8fb7d94e4e4b723790fbd19a02760df5ac816 # Version: Commits on Jun 14, 2026
-------------------------------------------------------------------------------------------------
Update readme,

--------------------------------------------------------------------------------------------------
libretro-gearsystem.mk a4f2cf7fdcb946ca3d150206c1b3e426fabd59c1 # Version: Commits on Jun 14, 2026
--------------------------------------------------------------------------------------------------
Update readme,

---------------------------------------------------------------------------------------------
libretro-opera.mk 64f35570aad94992f1122a810af6cc932862505a # Version: Commits on Jun 14, 2026
---------------------------------------------------------------------------------------------
MADAM: ignore bottom 2 bits in CCB processing

The bottom two bits of the address bus aren't even wired up to

MADAM. Most titles use properly aligned addresses but not all. This

patch ensures the pointers read from the CCB and the CCB address

itself are masked to align them to word boundry.

Fixes Ballz and possibly other titles that had unaligned addresses.,

----------------------------------------------------------------------------------------------------
libretro-parallel-n64.mk 2eff7ef440c8411d6b8670ea32d9b5a40492db12 # Version: Commits on Jun 13, 2026
----------------------------------------------------------------------------------------------------
libretro: only auto-force HLE graphics when the RSP plugin is on auto

The core forced the GFX task through the HLE emitter whenever the active

video plugin was not the one paired with the build's native low-level

path (angrylion for the threaded software build, parallel for the Vulkan

build). That override ran unconditionally, so selecting the cxd4 RSP

explicitly while using a different video plugin silently executed the

HLE display-list emitter instead of the requested low-level microcode,

contradicting the user's choice and making the two paths impossible to

compare. Gate the override on the RSP plugin being left on \auto\: an

explicit cxd4 or parallel selection is now honoured as low-level, while

auto keeps the previous convenience fallback.,

----------------------------------------------------------------------------------------------
libretro-ppsspp.mk 14dc5a51560628581c023235e9d35ec28fb14b6a # Version: Commits on Jun 14, 2026
----------------------------------------------------------------------------------------------
Merge pull request #21825 from hrydgard/ridge-racer-sprite

Fix the ugly line on Ridge Racer lens flares,

----------------------------------------------------------------------------------------------
libretro-prboom.mk 84cd28bd2d58bbfc8a2e48997862fefcac132c6e # Version: Commits on Jun 14, 2026
----------------------------------------------------------------------------------------------
Revert the above-eye 3D-floor water chain (translucent ceiling approach)

This reverts the four-commit chain that drew a swimmable water surface seen

across an opening from below it:

  1ae278f draw above-eye 3D-floor water as a translucent ceiling plane

  bb17de3 tint the submerged volume for above-eye 3D-floor water

  554a06b blend 3D-floor water at the map's alpha instead of fixed 50/50

  4327cc2 give 3D-floor water a solid colour when its flat is a bare marker

The approach is structurally wrong and cannot be salvaged by tuning.  It draws

the water as a single flat screen-space translucent span.  But the far wall of

the flooded room spans from its floor (~z -16) to its ceiling (z 448) within one

screen column, and only the part below the surface (z 138) is underwater.  A

flat span cannot express 'underwater up to the waterline, air above it' when the

far geometry crosses the surface mid-column, so the tint covers far above the

real water line regardless of clamp direction or alpha.  The result reads as a

blue sheet hung over the top of the opening, not a water surface -- visibly

worse than drawing nothing.

Correct 3D-floor water needs the surface clipped as a true horizontal plane

against the per-column far geometry (a real waterline), which is a substantial

renderer feature, not a span tweak.  Reverting until that exists rather than

shipping a broken effect.  Restores the exact pre-chain state (bb842a3); vanilla

demo hash unchanged (ab8eb93a72c8a66b).,

-------------------------------------------------------------------------------------------
libretro-ps2.mk 9b74364f0111b2159a47b8a3b12adbb2e255604f # Version: Commits on Jun 14, 2026
-------------------------------------------------------------------------------------------
common/GS: load and run on Windows 8 by resolving placeholder APIs at runtime

The fastmem area (HostSys.cpp) and the GS local-memory mirror (GS.cpp)

called VirtualAlloc2 / MapViewOfFile3 / UnmapViewOfFile2 directly.

These are Windows 10 1803+ exports, so as ordinary imports they land

in the DLL's import table and the loader cannot resolve the module on

Windows 8 / 8.1 - the whole core fails to load before any code runs,

even though both subsystems can operate without those APIs.

Resolve the three placeholder APIs once via GetProcAddress from

kernelbase.dll (added as PCSX2_HasPlaceholderAPIs in RedtapeWindows.h)

so they stay out of the import table, and branch on availability:

- HostSys fastmem: if the APIs are missing, Create() returns null and

  vtlb_Core_Alloc falls back to no-fastmem mode (the same path already

  taken when a 4 GB region can't be placed). Map()/Unmap() call through

  the resolved pointers, which are guaranteed present because the area

  only exists when Create() found all three.

- GS wrapped memory: GSLocalMemory cannot tolerate a null mapping (it

  memsets the buffer immediately), so a Win8 fallback is provided that

  reserves a contiguous repeat*size hole, releases it, and maps the

  file view into each slot with MapViewOfFileEx (available since

  Windows 2000). A flag records which path was used so the matching

  teardown runs in GSFreeWrappedMemory.

On Windows 10+ the resolver finds all three APIs on first use and the

existing placeholder workflow runs exactly as before - only the

otherwise-unreachable absence path is new - so behavior there is

unchanged. No effect on non-Windows builds.

NOTE: unverified on a real Windows toolchain. The added code was

compile-checked against a Windows target with MinGW (typedefs, call

shapes and control flow), but the full core was not built and this has

not been run on Windows 8 or Windows 10. Needs a Win10 SDK build and a

runtime check on both before merging.,

---------------------------------------------------------------------------------------------------
libretro-snes9x-next.mk 305ab6f1ab2c8dd03a70659a43001ec39bf9ac23 # Version: Commits on Jun 14, 2026
---------------------------------------------------------------------------------------------------
tile: register-only palette gather in TILE_ROW_PRE_SSE2 (no stack roundtrip)

Replaces the storel-to-stack + 8 byte-loads + align-load palette gather

with pextrw to GPR + pinsrw straight back into xmm.  Touches the central

TILE_ROW_PRE_SSE2 macro (six callers across the math-variant n1x1

helpers) and the open-coded SSE2 path in tile_draw_row_nomath_n1x1.

Found via autovec-aware codegen audit: gcc 13 -O3 lowers

    _mm_storel_epi64((__m128i *)pix_buf, pix);

    col_buf[0] = palette[pix_buf[0]];

    ... [eight byte indices] ...

    col_buf[7] = palette[pix_buf[7]];

into SEVEN redundant 16-byte stack stores of `pix` plus eight movzbl

loads at distinct offsets.  SLP analysis treats each byte-load as

needing its own non-aliasing copy of the source vector, so the spill

multiplier is one-store-per-byte-load.  Reading the indices through

pextrw goes register-only, and pinsrw places the gathered colors

directly in xmm so the subsequent mask/blend uses no scratchpad either.

Spill counts in the generated assembly (gcc 13.3 -O3 -msse2):

  function                          before        after

  DrawTile16_Normal1x1              spills=14     spills=0

  DrawTile16Add_Normal1x1           spills=15     spills=0

  DrawTile16Sub_Normal1x1           spills=14     spills=0

  DrawTile16SubF1_2_Normal1x1       spills=14     spills=0

The max-spill loop in tile.c (.L20167, xmm=94 spills=15) is gone; the

worst residual loop now has 7 spills, mean dropped from ~14 to ~3.

Microbench (x86_64 Linux, gcc 13.3, full per-row helper -- mask, db,

gather, store):

  -O3:  150.3 -> 137.4 ms   (1.094x speedup)  213 -> 233 Mrows/s

  -O2:  149.6 -> 137.1 ms   (1.091x speedup)  214 -> 234 Mrows/s

Bit-exact against the scalar reference over 200000 random trials,

and across 4000 row calls in the bench harness.

PIX_BUF / COL_BUF stay on the macro parameter list so the six callers

compile unchanged; the unused stack arrays are DCE'd at -O2/-O3.  The

parallel NEON path (TILE_ROW_PRE_NEON, NEON branch of

tile_draw_row_nomath_n1x1) is unchanged -- on NEON, vget_lane_u8

extracts directly into a GPR without a stack roundtrip, so the same

gcc lowering bug doesn't apply; a NEON-side audit can come separately.,

----------------------------------------------------------------------------------------------
libretro-stella.mk 6fcd49280bf923e171cfe87183d97ec20ce2fc99 # Version: Commits on Jun 13, 2026
----------------------------------------------------------------------------------------------
added cassette icons for MP3/WAV files,

---------------------------------------------------------------------------------------------------
libretro-swanstation.mk 93b213d805591c4f1488339c4a16f0b4cb68d44a # Version: Commits on Jun 14, 2026
---------------------------------------------------------------------------------------------------
gpu_sw: SSE2/NEON kernels for CopyOutRow16<RGBA8> and <BGRA8>

The two desktop-output specialisations of CopyOutRow16 -- RGBA8 and

BGRA8, used whenever the host display path is a 32bpp framebuffer

(the common case on Windows/Linux/macOS GL/Vulkan backends) -- were

the only ones left without a SIMD kernel.  The RGBA5551 and RGB565

variants for mobile/GLES targets already had SSE2 and NEON paths.

Each 16-bit MASB1555 source pixel expands to a 32-bit ARGB pixel

with the same per-channel scaling pattern as the existing kernels

(<<3 on each 5-bit channel; bit 15 expanded to 0x00/0xFF for RGBA,

hard-coded to 0xFF for BGRA, matching the scalar VRAM16ToOutput

specialisations bit for bit).

The kernels process 8 pixels per iteration:

  r8 = (v & 0x1F)         << 3

  g8 = ((v >> 5) & 0x1F)  << 3

  b8 = ((v >> 10) & 0x1F) << 3

  a_hi = (v >>arith 15)   << 8     // 0xFF00 if STP bit set else 0

  pair_lo = r8 | (g8 << 8)         // R in low byte, G in high

  pair_hi = b8 | a_hi              // B in low byte, A in high

  store unpacklo(pair_lo, pair_hi)

  store unpackhi(pair_lo, pair_hi)

The 16-lane interleave on SSE2 (punpcklwd/punpckhwd) produces u32

lanes in little-endian R|G|B|A order, which is the RGBA8 byte

layout.  BGRA8 just swaps the channel pairing (B|G in pair_lo,

R|A in pair_hi) and uses a constant alpha vector since BGRA8's

VRAM16ToOutput hard-codes alpha = 0xFF.

The NEON path uses vst2q_u16 to do the same interleave: storing

{r|g, b|a} produces the [r|g, b|a, r|g, b|a, ...] u16 sequence

which reads as [R|G|B|A, R|G|B|A, ...] in u32.

Tail pixels (width % 8) keep the scalar VRAM16ToOutput call exactly

as the RGBA5551 and RGB565 kernels do.

Microbench (x86_64 Linux, gcc 13.3, full 640-pixel row, 500K iters):

  RGBA8:

    -O3: 148 -> 75 ms  (1.97x)   2161 -> 4247 Mpix/s

    -O2: 351 -> 74 ms  (4.74x)    911 -> 4317 Mpix/s

  BGRA8:

    -O3: 119 -> 66 ms  (1.80x)   2683 -> 4827 Mpix/s

    -O2: 299 -> 64 ms  (4.68x)   1070 -> 5004 Mpix/s

Bit-exact across 33000 trials over widths 0..32 (exercising the

scalar tail at every remainder), input pixels drawn from the full

65536 u16 range.,

------------------------------------------------------------------------------------------------
libretro-tyrquake.mk 5e10328faf30161923fa0f918792fbeb7772ef5b # Version: Commits on Jun 14, 2026
------------------------------------------------------------------------------------------------
r_aclip: batch clipped fan into a single D_PolysetDraw dispatch

R_AliasClipTriangle clips an alias triangle against the frustum

planes via Sutherland-Hodgman, producing a polygon of up to 7

vertices, then triangulates it as a fan around vertex 0.  The

old code emitted one D_PolysetDraw call per fan triangle, with

the source carrying a 'FIXME: do all at once as trifan?' note

above the loop.

All fan triangles already share the same pfinalverts buffer

(R_AliasClipTriangle's stack-local fv[pingpong]) and the same

facesfront flag (inherited from the input triangle), so batching

is mechanical: build a mtriangle_t array on the stack with

vertindex[0..2] = (0, t+1, t+2) for t in [0, k-3], set

numtriangles = k - 2, and dispatch once.

mtri_fan[5] covers the worst-case fan size: a 3-vertex triangle

clipped against 4 frustum planes (left, right, top, bottom) grows

to at most 3 + 4 = 7 vertices, yielding a 5-triangle fan.  Z-clip

is handled separately upstream and never inflates the polygon

past the per-plane growth of the XY clips.

Performance impact on the SW path is modest (per-call D_PolysetDraw

overhead is small after the static-spans change in the previous

commit), but the structural change matters for two reasons.  First,

the GPU compute path in D_PolysetDraw (Phase 5b-06: the

g_rhi->dispatch_3d_alias short-circuit) is dispatch-heavy -- one

GPU submit per fan triangle on a partially-clipped entity is

exactly what the unclipped batching in R_AliasPreparePoints

(commit message at r_alias.c:477) was written to avoid.  Bringing

the clipped path under the same batching treatment closes the

remaining per-triangle-dispatch hole.  Second, the loop is now

straight-line code with no global-state mutation inside the body

(no per-iter writes to r_affinetridesc.ptriangles or to a shared

mtri scratch), which simplifies reasoning about the rasterizer's

preconditions when reading this code.

Bit-identical output: the fan triangles are generated in the

same order ((0,1,2), (0,2,3), (0,3,4), ...) and consumed by

D_DrawNonSubdiv / D_DrawSubdiv in the same order (their inner

loops iterate 0..numtriangles-1 with the same per-tri math),

so the resulting pixel emissions are unchanged.

Builds clean on x86_64, aarch64, and armv7 NEON crosses.,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-avm2 Area: AVM2 (ActionScript 3) T-compat Type: Compatibility with Flash Player

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants