diff --git a/engine/MUNGA_L4/L4VIDEO.cpp b/engine/MUNGA_L4/L4VIDEO.cpp index 1982a4b..f560208 100644 --- a/engine/MUNGA_L4/L4VIDEO.cpp +++ b/engine/MUNGA_L4/L4VIDEO.cpp @@ -3432,6 +3432,44 @@ DPLRenderer::DPLRenderer( mPresentParams.BackBufferWidth = screenWidth; mPresentParams.BackBufferHeight = screenHeight; } + else + { + // + // PIN THE WINDOWED BACKBUFFER (Gitea #56, and #50 -- the same bug). + // + // These were left at 0 for the windowed case, which tells D3D9 to derive the + // backbuffer from the device window's client area at CreateDevice time. Fine + // at startup -- but the device-lost recovery path saves and restores + // mPresentParams around Reset(), so it faithfully preserves the ZEROS and + // Reset re-derives the backbuffer from whatever the client area is at THAT + // moment. + // + // Field consequence: a player resizes or maximises the window (harmless by + // itself -- the cockpit layout lives in backbuffer space and the hit-test maps + // client -> canvas), then the device is lost (alt-tab, Steam overlay, monitor + // sleep, UAC prompt, RDP, driver hiccup). On recovery the backbuffer silently + // becomes the NEW client size while gBTCockpitCanvasW/H still describe the + // startup canvas -- so panels are drawn for one geometry and clicks are mapped + // in another. Buttons drift off their artwork, and at a big enough mismatch + // nothing is clickable at all (#50, "none of my MFDs clickable" while other + // players' worked). It needs BOTH steps in that order, which is why the + // operator -- who never resizes the cockpit window -- has never seen it. + // + // Recording the client rect here yields exactly what D3D would have derived, + // so startup behaviour is unchanged, but the save/restore now preserves a REAL + // size and Reset can never silently pick a different one. (Do NOT use + // screenWidth/screenHeight: those are the app's -res values, default 800x600, + // while the cockpit-surround window is sized independently -- pinning to them + // would shrink the backbuffer and break the composite.) + // + RECT rc; + if (hWnd != NULL && GetClientRect(hWnd, &rc) + && rc.right > rc.left && rc.bottom > rc.top) + { + mPresentParams.BackBufferWidth = (UINT)(rc.right - rc.left); + mPresentParams.BackBufferHeight = (UINT)(rc.bottom - rc.top); + } + } HRESULT hr; @@ -8067,6 +8105,45 @@ void } } +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// BTVerifyCockpitCanvasAfterReset (Gitea #56) +// +// The cockpit-surround layout is computed in BACKBUFFER space and clicks are +// mapped client -> backbuffer through gBTCockpitCanvasW/H (L4VB16.cpp +// BTCockpitMouseDown). With the windowed backbuffer now pinned at CreateDevice +// this should always agree -- so a mismatch here means the surface was re-created +// at a different size behind our back, which is exactly the state where panels +// draw in one geometry and clicks land in another. Say so, and re-sync, rather +// than drift silently for the rest of the session. +// +static void BTVerifyCockpitCanvasAfterReset(LPDIRECT3DDEVICE9 device) +{ + extern int gBTGaugeCockpit, gBTCockpitCanvasW, gBTCockpitCanvasH; + if (device == NULL || !gBTGaugeCockpit || gBTCockpitCanvasW <= 0) + { + return; + } + IDirect3DSurface9 *back = NULL; + if (FAILED(device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back)) + || back == NULL) + { + return; + } + D3DSURFACE_DESC desc; + if (SUCCEEDED(back->GetDesc(&desc)) + && ((int)desc.Width != gBTCockpitCanvasW + || (int)desc.Height != gBTCockpitCanvasH)) + { + DEBUG_STREAM << "[resize] Gitea #56: backbuffer is " << desc.Width << "x" + << desc.Height << " after Reset but the cockpit canvas is " + << gBTCockpitCanvasW << "x" << gBTCockpitCanvasH + << " -- clicks would be mis-mapped; re-syncing" << std::endl; + gBTCockpitCanvasW = (int)desc.Width; + gBTCockpitCanvasH = (int)desc.Height; + } + back->Release(); +} + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Execute Method, performs the rendering of one frame // @@ -8801,6 +8878,8 @@ void DPLRenderer::ExecuteImplementation(RendererComplexity, RendererOrigin::Inte mPresentParams.BackBufferCount = bbCount; mPresentParams.BackBufferWidth = bbWidth; mPresentParams.BackBufferHeight = bbHeight; + + BTVerifyCockpitCanvasAfterReset(mDevice); // Gitea #56 guard } ticks = HiResNowTicks(); @@ -9079,6 +9158,8 @@ void DPLRenderer::ExecuteIdle() mPresentParams.BackBufferCount = bbCount; mPresentParams.BackBufferWidth = bbWidth; mPresentParams.BackBufferHeight = bbHeight; + + BTVerifyCockpitCanvasAfterReset(mDevice); // Gitea #56 guard } } }