gitadora: add native dual fullscreen for Arena (#846)

## Link to GitHub Issue or related Pull Request, if one exists

Fixed https://github.com/spice2x/spice2x.github.io/issues/740

## Description of change

- Enable native D3D9 adapter-group dual fullscreen for the GITADORA
Arena model when the two-screen MAIN + SMALL configuration is selected
without windowed mode.
- Present MAIN and SMALL on their respective monitor heads while keeping
the invisible LEFT and RIGHT targets offscreen.
- Scope the new fake-swap-chain query behavior to the hidden GITADORA
two-head targets, preserving existing behavior for other games and
configurations.

The existing borderless-windowed two-screen path could not consistently
keep input and game timing synchronized and also reduced rendering
performance. Native dual fullscreen avoids that windowed composition
path.

## Testing

- Manually tested GITADORA Arena with separate MAIN and SMALL monitors
in fullscreen mode. Windowed mode still works if the user chooses to use
that.
- Confirmed both displays render correctly, touch input works on the
SMALL screen, gameplay input stays synchronized, and gameplay holds a
steady 60 FPS.
- Built `spicetools_spice64` at commit `e4a98e9` with the repository
Docker toolchain.
- Confirmed no new compiler warnings.
- Confirmed the forbidden static DLL import check passes.
- Confirmed the Windows 7 DLL compatibility check reports `All DLLs
OK!`.

---------

Co-authored-by: vgod <428979+vgod@users.noreply.github.com>
This commit is contained in:
Tsung-Hsiang Chang
2026-08-02 00:03:36 -07:00
committed by GitHub
parent c590b87cff
commit 3012139028
16 changed files with 1870 additions and 103 deletions
@@ -5,8 +5,13 @@
interface WrappedIDirect3DDevice9;
struct WrappedIDirect3DSwapChain9 : IDirect3DSwapChain9Ex {
WrappedIDirect3DSwapChain9(WrappedIDirect3DDevice9 *dev, IDirect3DSwapChain9 *orig) :
pDev(dev), pReal(orig), is_d3d9ex(false)
enum class NativeGroupHead { Unknown, Main, Small };
WrappedIDirect3DSwapChain9(
WrappedIDirect3DDevice9 *dev,
IDirect3DSwapChain9 *orig,
NativeGroupHead native_group_head = NativeGroupHead::Unknown) :
pDev(dev), pReal(orig), is_d3d9ex(false), native_group_head(native_group_head)
{
IDirect3DSwapChain9Ex *swapchain = nullptr;
@@ -16,8 +21,11 @@ struct WrappedIDirect3DSwapChain9 : IDirect3DSwapChain9Ex {
}
}
WrappedIDirect3DSwapChain9(WrappedIDirect3DDevice9 *dev, IDirect3DSwapChain9Ex *orig) :
pDev(dev), pReal(orig), is_d3d9ex(true)
WrappedIDirect3DSwapChain9(
WrappedIDirect3DDevice9 *dev,
IDirect3DSwapChain9Ex *orig,
NativeGroupHead native_group_head = NativeGroupHead::Unknown) :
pDev(dev), pReal(orig), is_d3d9ex(true), native_group_head(native_group_head)
{
}
@@ -53,6 +61,7 @@ struct WrappedIDirect3DSwapChain9 : IDirect3DSwapChain9Ex {
IDirect3DSwapChain9 *pReal;
bool is_d3d9ex = false;
NativeGroupHead native_group_head = NativeGroupHead::Unknown;
bool should_run_hooks = true;
};