Skip to content

Sync upstream (248) + Direct Composition on VulkanRenderer (PR #380 + #584) - #4

Draft
maxjivi05 wants to merge 295 commits into
test-branchfrom
pr380+584-dc
Draft

Sync upstream (248) + Direct Composition on VulkanRenderer (PR #380 + #584)#4
maxjivi05 wants to merge 295 commits into
test-branchfrom
pr380+584-dc

Conversation

@maxjivi05

Copy link
Copy Markdown
Owner

Syncs test-branch up to upstream/main (248 commits) and re-establishes Direct Composition on top of the new Vulkan compositor.

Why this wasn't a plain sync

Upstream PR WinNative-Emu#343 replaced the GLES GLRenderer with a native Vulkan compositor and deleted GLRenderer.java. Our Direct Composition work (PR WinNative-Emu#380) hooked directly into it, so ~255 lines had nowhere to land.

Rather than hand-port, this merges upstream PR WinNative-Emu#584 by @Vower2993, which is itself a port of PR WinNative-Emu#380 onto the Vulkan renderer plus substantial soft-boot hardening. Merging rather than copying keeps the original authorship of @Vower2993, Super Z and MaxsTechReview intact — their commits are ancestors here with their original SHAs.

Deliberately excluded

PR WinNative-Emu#584's ADPF performance-hint session and event-driven render-loop rewrite in XServerSurfaceView.java. Out of scope for a DC branch and independently risky — it changes every frame on every device. The coupled VulkanRenderer pieces (contentDirty gating, markContentDirty, requestInputRendersignalInputDirty) were removed with it, restoring upstream's requestCursorRender path.

The COMPOSER_OVERLAY story

Android only adds COMPOSER_OVERLAY usage automatically for buffers it composites itself. On the ASurfaceTransaction_setBuffer path it must be set explicitly, so PR WinNative-Emu#584 rebuilds the wrapper driver to allocate swapchain buffers with it and rejects buffers lacking it before they reach SurfaceFlinger.

The original soft-boot cause was a proof-of-life buffer allocating CPU_WRITE | COMPOSER_OVERLAY, which panics gralloc on Adreno 6xx qdgralloc, MediaTek and older Exynos. That buffer is gone.

Related industry precedent: Flutter hit the same class of bug and disabled AHB-based swapchains on all devices, not just the Xiaomi models that triggered it (flutter/flutter#160025, #160206). Keeping DC opt-in is the right posture.

Additional fixes in this branch

  1. Cursor vanished whenever DC engaged — affects every device. The cursor is composited in the Vulkan scene, which a DC-owned frame skips entirely. DC now declines while the cursor is visible.
  2. direct-composition.log was never flushed — the log meant to diagnose soft reboots lost its buffered tail in exactly that event.
  3. JNI undefined behaviourReleaseStringUTFChars called on a string literal when GetStringUTFChars returned NULL.
  4. The Xiaomi release-crash guard silently did nothing when ASurfaceTransaction_setOnComplete didn't resolve: nothing was counted, so the wait returned instantly. Bounded fallback added.
  5. Two data races on the in-flight transaction counter.

UI

  • The toggle moves to a compact "DC" chip in Graphics, as the Graphics Driver dropdown's labelTrailing — the same slot mechanism UnixLibs uses, so it sits right of the label, above Wrapper and left of Surface Effect with no layout shift. Grayed and inert when SurfaceCompositor.isAvailable() is false.
  • The HUD renderer label (DXVK / VKD3D) gains + DC in Material Green 800, driven by actual push success rather than the setting, so it only lights when DC is really driving the display.

Known tradeoffs

Verification

compileStandardDebugKotlin, compileStandardDebugJavaWithJavac, externalNativeBuildStandardDebug and a full assembleStandardDebug APK all succeed; libwinlator.so exports all six DC JNI entry points. Antutu, Ludashi and Pubg flavors also compile.

🤖 Generated with Claude Code

ribbit384 and others added 30 commits May 20, 2026 20:21
Revert "fix: small stick fix  (WinNative-Emu#441)"

This reverts commit be04297.
…e-Emu#446)

fix: automatically apply last installed driver from setup wizard to new containers
…ive-Emu#444)

* fix: robust registry editing and force native dinput8/xinput overrides

* fix: remove aggressive DLL override forcing to allow user persistence
* Virtual Gamepad: decouple style from layout, add GameHub profile, label themes, and ICP reset

- VisualStyle (Original/GameHub) now controls button shape only; element
  positions/sizes always come from the active ICP profile. GameHubLayout no
  longer relocates controls at draw time.
- Add bundled "GameHub" layout profile (controls-7.icp) capturing the GameHub
  button positions as a real, selectable ICP.
- Rename the "Default" button-label theme to "Original".
- importProfile no longer overwrites bundled built-in profiles, so importing a
  legacy ICP whose name collides with a built-in creates a visible profile.
- Built-in profiles are now editable in place (no forced duplicate). A pristine
  snapshot of every profile is kept in profile_backups/ at install/download/
  import/create time, and a Reset action in the profile menu restores it.
- copyAssetProfilesIfNeeded copies missing built-ins only, never overwriting
  user-edited ones, and keeps the built-in backups refreshed.

* feat: comprehensive virtual gamepad update and input control fixes

* feat: improve GameHub Range Button rendering and auto-reset labels for custom profiles

* feat: decouple label switching on GameHub and refine dynamic color fetching

* fix: ensure themed profiles are loaded for dynamic color fetching

---------

Co-authored-by: MaxsTechReview <maxjividen@gmail.com>
* Fixes a bug in setup wizard where if you deleted last driver installed the container creation still tried to apply that driver.
* links the show touchscreen controls toggle to the disabled selection so applying disabled turns toggle to off position.
Updated control bindings to stick, and added a d-pad for arrow keys
Remove redundant isActivityPaused calls. Re-registers VulkanRenderer listeners on surface re-attachment to ensure mouse responsiveness.
* feat: relocate save management to container settings and improve export logic
* feat: Export entire user folder.
* feat: implement advanced container naming with auto-incrementing suffixes
* feat: add filters to save export/import and include ProgramData
* feat: add confirmation dialog for save exports
* feat: add Package Cache to filter and implement modal loading UI for saves
* feat: show selected filename in picker

---------

Co-authored-by: local tester <local-tester@example.com>
Xnick417x and others added 30 commits July 21, 2026 08:42
* arm64ec: remove zink_dlls extraction, use builtin opengl32 (unix Zink)

* DRI3: accept AHB modifier 1256 for zero-copy hardware-buffer scanout

* Graphics: only disable Kopper for Steam launches
…e in-game control (WinNative-Emu#631)

* feat(reshade): drop-in effects, catalog, multi-effect loadouts + live in-game control

Adds ReShade (.fx) effects for Vulkan-backed (DXVK/VKD3D) games via the bundled
vkBasalt layer, with a per-game/per-container loadout, an in-app catalog, and live
in-game control.

- Loadout: ordered set of effects with Solo (live A/B switch) or Stack (layered)
  mode + per-effect reflected ui_* parameters; pre-launch editor in the ReShade
  settings section (add/remove/reorder), persisted via reshadeLoadout/reshadeMode
  extras (legacy single-effect reshadeEffect migrates forward).
- In-app catalog (reshade.json via RESHADE_CATALOG_URL buildConfigField): search,
  verified download, and per-effect delete of installed effects.
- In-game drawer: own XServerDrawerReshadePane.kt (DrawerPane.RESHADE + RailPaneSpec
  + when(pane) dispatch) — master enable, Solo/Stack selector, per-effect enable
  toggles + parameter sliders, all applied live.
- Live control with no recompile: all loadout effects are compiled into the vkBasalt
  chain at launch; a live-reload patched libvkbasalt.so (patches/, build-vkbasalt.yml)
  watches the config mtime and re-reads each effect's _enabled gate + UBO uniforms.
  Ships in extra_libs.tzst with version-aware re-extraction (no imagefs reinstall).
- 22-locale strings. Based on the post-refactor main.

Engine: DadSchoorse/vkBasalt (zlib); bundled by Pipetto-crypto.

* reshade: vendor vkBasalt submodule, hybrid live control, catalog + fixes

- vkBasalt as a submodule (app/src/main/cpp/vkbasalt); ship the built
  libvkbasalt.so in extra_libs.tzst, strip-debug so the symbol table stays
- catalog URL -> nicholasx417/WinNative-Components/Reshade.json (no parser change)
- atomic vkBasalt.conf writes (temp+rename); reserve built-in effect key names
- multi-effect texture/include paths resolve; command-buffer realloc before re-record
- .fx scraper: keep defaults outside guessed bounds, strip block comments, scalar
  color, step after clamp, MAX_EFFECTS cap; per-game 'no reshade' override
- catalog dialog as cards with download/delete chips + stableCursor scroll
- drop docs/reshade.md, the build workflow, and patches/ (submodule replaces them)

* file picker: A selects instead of hover, fix stale Start selection

- selectedFile is a stable state so Start confirms the current pick, not a
  per-directory one captured stale in the handler
- A selects and illuminates bright; hover only moves the cursor
- Add Custom Game name field focuses and opens the keyboard on A

---------

Co-authored-by: Xnick417x <nicholas.german20@gmail.com>
* HUD: prefer Zink renderer window over bare-Vulkan when labeling

* HUD: keep renderer label when Zink probe window is destroyed mid-run

Mesa tears down its 1x1 Zink probe drawable before the game window maps, so an
empty renderer scan no longer forces the label back to Vulkan. Revert only once
a window that actually presented a frame is gone, or the app returns to the
desktop shell.
…inNative-Emu#660)

The name field only allowed focus while nameEditing was set, which only the controller activate path did; a touch tap was refused focus so the keyboard never appeared. Tap-down now sets nameEditing too, entering the same focus+IME path.
…inNative-Emu#661)

Dropdown in Components (General group), gated to arm64ec, saved per-container
and overridable per-shortcut. At boot the resolved mode extracts the Windows
Mesa opengl32 DLLs (Windows Zink) or restores wine's builtin (Unix Zink), keyed
off the libgallium_wgl marker so a container and its shortcuts self-correct.
Reorder settings sidebar to Variables, Input, Components; add localized Zink
Mode label to all locales.
* Add swipe activation for touchscreen controls

Sliding off a touch button no longer leaves the finger dead: buttons press on
entry and release on exit, d-pad engages steering on entry and hands off when
exited onto another control, radial menus swipe-open and close when pulled out
to another control. Range buttons unchanged; disabled in map-to-right-stick
mode. Multi-touch capture stays per-pointer.

* Add per-button Swipeable option to controls editor

Checkbox beside Toggle Switch for buttons and d-pads, checked by default.
Unchecked elements only activate on a direct tap and are skipped by swipe
capture; they can still start a swipe chain after a tap. Stored per element
in the profile, older profiles load as swipeable. Label in all locales.
* File manager: multi-select for batch copy/cut/delete

Add a Multi-select toggle chip to the manager footer. With it on, tap or
controller A toggles selection on files and folders; long-press or X opens
the context menu acting on the whole selection (Copy/Cut/Delete show counts,
Rename/Run/Create Shortcut stay single-item).

clipboard is now a list, so paste moves every copied item in one pass behind
a single byte-weighted progress bar; cancel removes only the in-flight
destination. Copy and Cut auto-exit multi-select, otherwise tapping a folder
selects instead of navigating and the paste destination is unreachable.

Selection clears on directory change; controller B exits multi-select before
falling through to closing the dialog.

Footer chips (Paste, Folder, Multi-select) share one 78dp width with centered
content, replacing the wider New Folder chip. Short chip labels get their own
string keys and are translated for all locales along with the new count,
batch-confirm and batch-progress strings.

* File manager: extract zip, 7z, tar, xz and zstd archives

Add an "Extract here" action for archive files in the manager context
menu. Extracts into a new folder named after the archive, suffixed
" (2)" when that name is taken, reusing the existing transfer progress
overlay so cancel removes the partial output.

New ArchiveExtractor handles zip and 7z directly, and streams tar
through gzip/bzip2/xz/zstd decompressors. Single-stream archives are
sniffed for the ustar magic, so a bare .xz holding a tar extracts as a
tar instead of one blob. Entry paths are checked against the destination
to reject traversal, and symlink/hardlink entries are skipped.

Uses commons-compress, tukaani xz and zstd-jni, all already declared;
no native code is involved.

* File manager: extract to a chosen folder, and detect archives by magic

Add "Extract to..." next to the existing "Extract here". It puts the
archive on the clipboard so the footer chip, relabelled Extract,
confirms the destination after navigating. "Extract here" keeps
extracting into the current folder and no longer needs the clipboard,
so it leaves a pending copy alone.

Clipboard carries a COPY/CUT/EXTRACT mode instead of an isCut flag.

Detect the archive format from magic bytes, falling back to the
extension only when nothing matches. This makes .wcp work, since the
name cannot say whether the payload is xz or zstd, and any other
renamed archive along with it.

* Fix controller nav for file manager overlays and dynamic footer chips

Single-row pane registries ordered their items by registration order
rather than screen position, so a chip added later sat at the end of
the row no matter where it drew. The Paste and Extract chips appear
only once the clipboard is filled, which left them past the Close
button instead of at the left edge. Order single rows by x.

The file manager returned a null registry while the rename, new folder,
delete, container picker or transfer overlay was up, which left those
popups with no navigable items at all. Give them their own registry,
reset it as each opens, and register the container picker rows.

* File manager: Start button pastes or extracts the clipboard in place

With something on the clipboard, Start now performs it in the current
folder instead of closing the manager, covering copy, cut and an
archive queued by "Extract to...". Start still closes the manager when
the clipboard is empty, and the existing overlay guard keeps it from
firing while a transfer is running.

* File manager: only offer Run and Create Shortcut for executables

Both actions were gated on the entry being any file, so a shortcut
could be made for a zip or any other extension and would sit dead in
the library. Gate them on the same exe/bat/cmd list the executable
picker filters by, and have that picker read the list from one place
so the two cannot drift.
Update graphics wrapper: Mali RGBA8 swapchain, strip CullDistance, patch BCN view-format list
…Emu#668)

values-pl/arrays.xml and values-hi/arrays.xml still carried the full
legacy translation and overrode the default arrays. Dropdown selections
are persisted as identifiers parsed from the visible label, so the
translated graphics_driver_entries saved graphicsDriver as vortek/turnip/
virgl/adreno instead of wrapper/wrapper-leegao/wrapper-gamenative, and
the wrapper archive was never extracted at launch. dxwrapper, emulator,
present mode, wincomponent, bcn emulation and desktop theme broke the
same way.

Trim both to desktop_background_type_entries only, matching every other
locale. That array is index-mapped to BackgroundType so its labels are
safe to translate.
…inNative-Emu#669)

Clamp the exported WRAPPER_VK_VERSION to the minor the driver actually
reports, so selecting 1.4 on a 1.3 driver no longer advertises an
unsupported version (previously the device patch level was appended to
the chosen minor, producing values like 1.4.289 on a 1.3.289 driver).

Drop the duplicated pl/hi vulkan_version_entries arrays; they were
untranslated copies and, lacking the new entry, would have pinned those
locales to 1.1 through the index-based selection fallback.
* Add FEXCore Performance TSO, Extreme, Extreme TSO and Denuvo presets

Performance TSO is Performance with TSO re-enabled and SMC checks set to
mtrack, and is now the default preset for new containers. Extreme and
Extreme TSO drop SMC checks entirely and enable the dynamic L1 / disabled
L2 cache paths; Denuvo pins full SMC checks with a raised instruction
limit and the hypervisor bit hidden.

Also adds WRAPPER_DMAHEAP_CACHED to the environment variable picker as a
0/1 toggle, and translates the four new preset names across all locales.

* Keep side-by-side settings dropdowns on one controller nav row

SettingDropdown rendered its label as a chip-sized Row when labelTrailing
was present and as bare text otherwise, so the field below it started
lower. PaneNav groups rows by center-Y, so the FEXCore Version and Preset
dropdowns were split into separate nav rows; left from Preset then took
the lone-item branch and exited to the sidebar instead of moving onto
Version. Use one fixed-height label row for both cases.

Also mirror left in the right handler: a lone-item row whose item has no
adjust callback now falls back to the right edge handler instead of
silently doing nothing.
…ive-Emu#671)

* Run .msi, .bat and .cmd from the exe pickers and file manager

.msi was missing from the executable extension set, so it was hidden in the
Add Custom Game picker and had no Run or Create shortcut action in the file
manager. The shortcut settings picker kept its own exe-only list and never
picked up .bat/.cmd.

Launching was broken for all three: the target path went straight to
winhandler.exe, but .msi/.bat/.cmd are not PE images so CreateProcess could
not start them. Non-PE targets now run through their interpreter --
msiexec.exe /i with /passive /norestart, or cmd.exe /c -- at both the boot_exe
and custom shortcut launch sites.

Both pickers and both validators now share DirectoryPickerDialog.ExecutableExtensions.

* Component installer: pass /norestart to MSI steps

An MSI that requests a reboot restarts unattended under /passive and /q,
which tears down the Wine session mid-install. Append /norestart to the
msiexec command rather than folding it into the /passive default, so steps
that supply their own arguments (msxml3 and msxml4 use /q, which replaces
the default outright) are covered too. install_exe steps are unaffected.

* Default new containers to the Performance TSO FEXCore preset

Creating a container with the manual button opens the settings dialog with no
container, so the preset dropdown fell back to the fexcore_preset preference
whose default was still PERFORMANCE. The dialog then wrote that back over the
PERFORMANCE_TSO already set by buildLaunchReadyData. Auto-create was correct
because it never opens the dialog. Update both stale fallbacks.
WinNative-Emu#672)

* Gyro mouse: allow mouse and keyboard bindings as the hold/toggle activator

When experimental mouse movement is enabled the activator dropdown now lists mouse
and keyboard bindings alongside gamepad buttons, stored in gyro_mouse_trigger_binding
(default right mouse button). Activation is detected at the pointer/key injection
points and the relative-mouse path, so presses from a physical mouse or keyboard,
on-screen controls or the touchpad all drive hold and toggle. A rising-edge guard
keeps the toggle correct when one press arrives on both paths.
Apex and wings were swapped, so all four arrows rendered pointing at
the center. Apex now sits outward and the wings pull back, matching
the chevron convention used by the other visual styles.
With the setting disabled, four paths in TouchpadView still injected a
mouse button: the simTouchScreen delayed left press, the touchscreen
one-finger down press, the two-finger-lift right click, and the
two-finger-far-apart left press. Their releases already sat inside the
tapToClickEnabled gate, so a press latched down and re-fired on each tap.

Disabling the setting now also releases any button still held. Cursor
movement, aiming and scrolling are unaffected, and behavior with the
setting enabled is unchanged.
* Persist drives created inside Wine across container boots

dosdevices is now the source of truth for drive mappings. The boot rebuild no
longer deletes every drive letter before recreating them from the container
config, and bind paths are derived from the prefix, so a drive added in winecfg
is exposed to the guest instead of being dropped. The container config seeds
only a prefix that has no drives yet, which keeps defaults working on a fresh
container and restores them if the prefix is ever rebuilt.

* Let the directory picker location box accept a typed path

Tapping the current-path card opens a text input prefilled with the current
directory, focused with the keyboard shown. A directory navigates there, a file
path opens its parent with the file selected, anything else reports that the
path was not found. The card is registered as a pane-nav item so it is reachable
without touch.

* Route pane-nav to the path popup and let Start confirm it

The path input was only wrapped in the overlay registry, so d-pad keys still
resolved to the grid registry and moved the directory selection behind it,
leaving OK and Cancel unreachable. Its visibility now feeds the registry
selector, the Start guard, the dismiss chain and the overlay reset. Start
confirms the typed path instead of acting on the picker underneath, sharing one
apply path with the OK button.
…e-Emu#677)

* Make controls editor element placement pixel-accurate

Drags were quantized to a width/100 grid via a floor, so positions between
grid lines were unreachable and every move landed short of the finger.
Dragging and the add-element cursor now use exact pixel coordinates.
Profile loading rounds instead of truncating, so a save/reopen cycle no
longer loses a pixel.

* Make the editor cursor cross follow the finger

The cross only jumped to its new spot on release. It now snaps to the
touch point on down and tracks continuously while dragging empty space.
…tive-Emu#676)

Bundle InputControl32.exe and InputControl64.exe and stage them into the
container alongside the graphics test exes; stageGraphicsTestExes is renamed
to stageBundledTestExes since it now covers both. Seed Start Menu entries for
both, extend HeroBootChoice with Input32/Input64 so the hero boot popup offers
all four tests, and translate hero_input_tests_title to all 22 locales.
WinNative-Emu#622)

Adds a Retro section to the library: console games run in-app rather than through Wine, with one shared menu, one shared pad and one shared save story across every system.

Four runtimes sit behind that, each hosted in WinNative's own process:

  - libretro, via a vendored libretrodroid, for the cartridge systems
  - ARMSX2 for PS2
  - Dolphin for GameCube
  - a LOVE-based reimplementation of Gen 1 Pokemon, which renders the world as voxels when the player asks for it Cores, BIOS and the 3D engine ship in a downloadable bundle rather than the APK, installed from Settings > Retro and updated in place. Games are added as ordinary shortcuts, so everything the library already does -- artwork, playtime, cloud saves, pinned launchers -- applies to them.

The Retro drawer is one composable driven by callbacks, not by libretro, which is what lets all four runtimes present the same menu. Display, Sound, Performance, HUD, Controls, System and save slots are built from whatever the running system reports, so a setting shown is a setting that system actually has.

The 3D engine is the odd one out and worth knowing about. It is not an emulator -- it never executes the ROM -- so it has no core variables to read and no save state to serialise. It talks to the host over a file
channel instead, publishing its own option rows and save slots and taking commands back. Two consequences: the menu shows the engine's real values rather than a mirror the host maintains, and a mod that adds settings appears in the menu for free. RetroAchievements is unavailable on that path for the same reason, and says so rather than showing an empty list.

Notes for review:
  - The engine's Lua changes are applied at build time by scripts in its own fork, never committed there, so the daily upstream sync cannot conflict with them. A contract check runs in that fork's CI before it publishes, because the host calls engine functions defensively and a rename upstream would otherwise leave the menu quietly broken.
  - Engine saves live in its own directory, not a libretro .srm, so they are staged into cloud sync separately. Which of the two a Game Boy shortcut syncs depends on whether its 3D toggle is on -- they are genuinely different saves.
  - The engine's control channel does its file reads and writes on its own background thread; nothing in the retro path polls storage from the UI thread.
  - The on-screen D-pad sends a single direction: whichever axis the thumb has travelled further along, with hysteresis so it does not chatter on the diagonal. Retro pad only; sticks are unchanged.
* Consume LibretroDroid as a published AAR instead of building it

The libretro frontend now lives in WinNative-Emu/LibretroDroid on the
winnative branch, alongside the core forks. Its CI builds the AAR with
the pinned NDK and publishes it like any other core; this repo fetches
that artifact instead of compiling the module.

- Removes the vendored libretrodroid module (207 files) and with it the
  oboe and libretro-common submodules
- tools/libretrodroid.version pins the release tag and SHA-256; the
  fetch task verifies the checksum and fails the build on a mismatch,
  so the artifact stays as auditable as a checked-in binary without
  carrying the bytes in git
- Restores validate-wrappers: true in both workflows. The dedicated
  wrapper-validation step and its allow-checksums entry existed only
  because oboe's OboeTester sample ships a wrapper jar that is not an
  official Gradle release wrapper. With oboe gone, this repo's only
  wrapper jar is its own official one
- EMULATOR_CREDITS.md points the GPL-3.0 source and the rcheevos/SGSR
  licence texts at the fork, since those paths no longer exist here

Verified locally: AAR builds 16k-page aligned, app compiles against it,
assembleStandardDebug produces an APK containing liblibretrodroid.so.

* Drop the libretro Dolphin core

GameCube and Wii run on embedded standalone Dolphin, which is built by
WinNative-Emu/dolphin and already reaches the device as libmain.so in the
Retro-Consoles bundle. The libretro core was a second, unrelated build of
Dolphin from libretro/dolphin, reachable only when wn.gc.embedded is false
-- a flag with no UI writing it and a default of true, so in shipping
builds it was 15.7 MB of Git LFS that nothing could load.

- Deletes app/src/main/jniLibs/arm64-v8a/libdolphin_libretro_android.so
  and the LFS rule that tracked it, leaving no *_libretro_android.so in
  the repo at all
- RetroCoreManager.resolveCore loses its nativeLibraryDir special case, so
  every core now resolves from the bundle uniformly

The dead DOLPHIN_LIBRETRO_CORE constant and the wn.gc.embedded fallback
branch are left for the Phase 7 cleanup in cores/DOLPHIN_EMBED.md, which
changes settings-screen routing and wants device testing.

* Separate 3D and libretro saves, strip retro comments, finish translations

Cloud saves: a Game Boy shortcut with the 3D toggle on keeps its progress
in the LOVE engine, with the toggle off it keeps an .srm. Both modes were
computing the same customGameId, so one cloud slot held whichever ran
last, and retroSaveDir picked the destination from the live toggle rather
than from the backup being restored. Toggling 3D therefore restored one
mode's save into the other's directory and both games started fresh.

- Engine saves now take an id of their own, and parseCustomGameId strips
  the marker so shortcut lookup is unchanged
- retroSaveDir takes the gameId and derives engine-vs-libretro from it,
  falling back to the toggle only where no id is in hand
- The cloud saves screen passes the id it is already displaying

Legacy unsuffixed backups stay with the libretro path, so an existing
.srm restores as before. Engine progress already on the device is
untouched; only its cloud copy needs one fresh backup.

Also removes every comment from app/src/main/feature/retro (995 lines
across 10 files, done with a Kotlin lexer so URLs inside string literals
were left alone) and fills in the 17 Gen 1 engine strings that were
missing from all 22 locales.
Syncs the fork up to upstream/main. The significant conflict is upstream
PR WinNative-Emu#343, which replaced the GLES GLRenderer with a native Vulkan
compositor; GLRenderer.java is deleted upstream, so the Direct
Composition render hooks and the activity-side DC lifecycle that were
built against it are dropped here.

The DC support files (surface_compositor.c, DirectCompositionLayer,
SurfaceCompositor, the Container/settings plumbing and the Drawable
fence field) are retained. They are re-wired onto VulkanRenderer in the
following merge of upstream PR WinNative-Emu#584, which ports this feature to the new
renderer.

Conflict resolutions:
  * CMakeLists.txt        - union: keep surface_compositor.c and
                            upstream's ring_fence.c / sync_fence.c
  * GPUImage.java         - take upstream's Vulkan rewrite, re-add the
                            getHardwareBufferPtr() accessor over ahbPtr
  * Drawable.java         - keep upstream's new scanout/presented-source
                            fields plus our volatile scanout fields and
                            the acquire-fence FD
  * Container.java        - keep EXTRA_DIRECT_COMPOSITION; drop the
                            STEAM_TYPE_* constants removed upstream
                            (verified unreferenced)
  * ContainerSettings...  - keep both the DC and useUnixLibs settings
  * XServerDisplayActivity- take upstream; our changes to this file were
                            DC wiring only
  * GLRenderer.java       - accept upstream deletion
…kanRenderer

Adopts the Direct Composition work from WinNative-Emu#584
("Direct Composition + ADPF + hardware fence sync + event-driven render
loop") by Vower2993, with commits authored by Super Z, Vower2993 and
MaxsTechReview. That PR is itself a port of PR WinNative-Emu#380 (this fork's original
GLES Direct Composition work) onto the native Vulkan compositor from PR
WinNative-Emu#343, plus substantial soft-boot hardening. Merging rather than copying
so the original authorship is preserved.

What this brings in:
  * surface_compositor.c rewritten with soft-boot hardening — the
    256x256 magenta smoke-test buffer is gone (CPU_WRITE +
    COMPOSER_OVERLAY panics some gralloc implementations), dstX/dstY are
    validated before reaching ASurfaceTransaction, release() waits for
    in-flight transactions, and buffers without COMPOSER_OVERLAY usage
    are rejected outright.
  * DirectCompositionLayer / SurfaceCompositor rewritten against the new
    renderer, with an explicit ADATASPACE_SRGB dataspace.
  * VulkanRenderer DC hooks: candidate scan, push/hide with disengage
    hysteresis, fence-FD draining, self-detach after repeated failures,
    and a DC state listener.
  * FrameRating HUD "+ DC" indicator and shortcut-level persistence.
  * wrapper.tzst rebuilt to allocate swapchain buffers with
    COMPOSER_OVERLAY usage and native BGRA tagging.

Deliberately excluded (out of scope for this branch):
  * The ADPF performance-hint session and the event-driven render-loop
    rewrite in XServerSurfaceView.java — reverted to upstream. The
    coupled VulkanRenderer pieces (contentDirty gating, markContentDirty,
    requestInputRender -> signalInputDirty) are removed too, restoring
    upstream's requestCursorRender path in onPointerMove.

Conflict resolutions:
  * surface_compositor.c, DirectCompositionLayer, SurfaceCompositor -
    take PR WinNative-Emu#584; ours were the superseded GLES-era versions and the
    auto-merge had concatenated both, duplicating JNI symbols.
  * Container / GPUImage / Drawable / strings.xml - drop our duplicate
    DC members that the auto-merge left alongside PR WinNative-Emu#584's.
  * GameSettings.kt - take PR WinNative-Emu#584; the container-edit-mode gate is
    dropped now that the setting persists per shortcut.
  * XServerDisplayActivity - keep both upstream's reshade teardown and
    PR WinNative-Emu#584's DC release.
  * wrapper.tzst - take PR WinNative-Emu#584's COMPOSER_OVERLAY build. Note this is
    12 days older than upstream's WinNative-Emu#662 driver update; the overlay usage
    bit is required for DC to engage at all, so the patch needs rebasing
    onto the newer driver as a follow-up.

Co-Authored-By: Vower2993 <81265405+Vower2993@users.noreply.github.com>
…Emu#584 merge

The auto-merge kept both our GameSettingsStateHolder.directComposition
and PR WinNative-Emu#584's, which made every reference to it an overload-resolution
ambiguity. Keeps PR WinNative-Emu#584's declaration.

Verified: compileStandardDebugKotlin, compileStandardDebugJavaWithJavac
and externalNativeBuildStandardDebug all succeed, and libwinlator.so
exports all six Direct Composition JNI entry points.

Co-Authored-By: Vower2993 <81265405+Vower2993@users.noreply.github.com>
Audit of the Direct Composition path for behaviour on other vendors,
SoCs and Android versions. Five defects fixed:

1. Cursor vanished whenever DC engaged. The cursor is composited in the
   Vulkan scene, and a DC-owned frame skips that composition entirely,
   so the SC layer covered a frame that never had a cursor drawn on it.
   Fullscreen sessions hide the cursor at setup so the common path is
   unaffected, but windowed and touchpad use lost the pointer. DC now
   declines to engage while the cursor is visible, the same way it
   already declines for the magnifier overlay.

2. direct-composition.log was never flushed. The log exists to diagnose
   SurfaceFlinger crashes and soft reboots, which is exactly when the
   buffered tail is lost. Now flushed per line.

3. Undefined behaviour in nativeCreateFromWindow: when
   GetStringUTFChars returned NULL the code fell back to a string
   literal and then passed that literal to ReleaseStringUTFChars. The
   JNI-owned pointer is now tracked separately.

4. The release-time wait that prevents the Xiaomi/HyperOS SurfaceFlinger
   crash depends on ASurfaceTransaction_setOnComplete. If that symbol
   does not resolve, nothing is ever counted, inflight_wait_all()
   returns immediately, and the protection silently disappears on
   exactly the devices most likely to need it. Falls back to a bounded
   32ms wait before release, and warns once at init.

5. Data race: g_inflight_count was read outside g_inflight_mutex in
   nativeWaitForPreviousFrame, and g_transaction_pending outside it in
   wait_for_transaction_gate. Both checks now happen under the lock.

Not changed: no device/brand blocklist is reintroduced. Upstream PR WinNative-Emu#584
removed its Xiaomi blocklist in favour of the per-container opt-in, and
that remains the right gate while the feature is in testing. The
COMPOSER_OVERLAY usage check is the real safety net — Android only adds
that flag automatically for buffers it composites itself, so it must be
set explicitly for the setBuffer path, and buffers without it are
rejected before they ever reach SurfaceFlinger.

Co-Authored-By: Vower2993 <81265405+Vower2993@users.noreply.github.com>
…chip

Replaces the Direct Composition checkbox with a compact "DC" chip in the
Graphics section, rendered as the Graphics Driver dropdown's
labelTrailing. That places it to the right of the "Graphics Driver"
label, above the Wrapper dropdown and left of "Surface Effect", using the
same slot mechanism as the UnixLibs chip so nothing shifts.

DirectCompositionChip mirrors UnixLibsChip's geometry (6dp corners,
10x2dp padding, SettingLabelSize) so the two match, and follows the same
lit/grayed convention: accent blue when enabled, dim when off.

The chip is inert and gray when SurfaceCompositor.isAvailable() is false,
so devices below API 29 or without the ASurfaceControl symbols can't arm
a toggle that could never engage.

The setting keeps PR WinNative-Emu#584's per-shortcut persistence, overriding the
container value, and the session gate already resolves shortcut first
with container fallback.

Co-Authored-By: Vower2993 <81265405+Vower2993@users.noreply.github.com>
The HUD renderer label (DXVK / VKD3D) gains a "+ DC" suffix while Direct
Composition is actually driving the display. Recolours PR WinNative-Emu#584's badge
from Material Green 500 to Green 800: the HUD already uses a bright
#76FF03 for the FPS readout, so the darker green reads as a state badge
rather than another metric.

The span now starts at "+" rather than the preceding space, so only the
"+ DC" glyphs are tinted.

The badge tracks real state, not the setting: it is driven by
dcLayerActive, which only becomes true after a buffer is successfully
pushed to SurfaceControl, and every transition — hide, self-detach after
repeated failures, and target swap — notifies the listener, so it can't
stick on after DC stops being used.

Co-Authored-By: Vower2993 <81265405+Vower2993@users.noreply.github.com>
Removes narration, phase-by-phase development history, restatements of
the code below them, and a stale absolute path to a research report on
someone else's machine. Net -217 lines, all comment.

Kept the comments that carry information the code doesn't: the gralloc
combination that panics on some devices, why there is no smoke-test
buffer, why negative destination coordinates are rejected, why the
layer must not be released with a transaction in flight, why OPAQUE
avoids the Snapdragon SDR-on-HDR brightness boost, and the threading
constraints behind each volatile and lock.

Verified with compileStandardDebugKotlin,
compileStandardDebugJavaWithJavac and externalNativeBuildStandardDebug.

Co-Authored-By: Vower2993 <81265405+Vower2993@users.noreply.github.com>
Moving the toggle to a "DC" chip left the translated
session_display_direct_composition string orphaned and the control
announced as just "DC". Reuses the existing label as the chip's
contentDescription, which both restores an accessible name and keeps the
15 locale translations PR WinNative-Emu#584 added in use.

Co-Authored-By: Vower2993 <81265405+Vower2993@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants