From 12655fa5a36a4bc43d7dd143c880d4bcd98b3c0d Mon Sep 17 00:00:00 2001 From: FunkyFr3sh Date: Sun, 7 Oct 2018 13:42:32 +0200 Subject: [PATCH] stop drawing and release d3d9 on alt+tab --- ddraw.rc | 2 +- inc/main.h | 1 + src/main.c | 15 +++++----- src/render_d3d9.c | 71 +++++++++++++++++++++++++++++++---------------- 4 files changed, 57 insertions(+), 32 deletions(-) diff --git a/ddraw.rc b/ddraw.rc index 99f9d1d..114b6cb 100644 --- a/ddraw.rc +++ b/ddraw.rc @@ -2,7 +2,7 @@ #define vxstr(a,b,c,d) str(a##.##b##.##c##.##d) #define str(s) #s -#define VERSION 1,2,0,2 +#define VERSION 1,2,0,3 1 VERSIONINFO FILEVERSION VERSION diff --git a/inc/main.h b/inc/main.h index a8db950..2dc8246 100644 --- a/inc/main.h +++ b/inc/main.h @@ -99,6 +99,7 @@ typedef struct IDirectDrawImpl BOOL wine; int sleep; LONG resetDirect3D9; + LONG minimized; } IDirectDrawImpl; diff --git a/src/main.c b/src/main.c index 4c1c3e5..6a0d536 100644 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,7 @@ BOOL screenshot(struct IDirectDrawSurfaceImpl *); extern HMODULE hD3D9; extern D3DPRESENT_PARAMETERS D3dpp; +extern BOOL UseDirect3D9; IDirectDrawImpl *ddraw = NULL; @@ -631,8 +632,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { ChangeDisplaySettings(&ddraw->render.mode, CDS_FULLSCREEN); - D3dpp.Windowed = FALSE; - InterlockedExchange(&ddraw->resetDirect3D9, TRUE); + InterlockedExchange(&ddraw->minimized, FALSE); if (wParam == WA_ACTIVE) { @@ -650,11 +650,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) /* minimize our window on defocus when in fullscreen */ if (!ddraw->windowed) { - ShowWindow(ddraw->hWnd, SW_MINIMIZE); + if (!UseDirect3D9) + ShowWindow(ddraw->hWnd, SW_MINIMIZE); + ChangeDisplaySettings(&ddraw->mode, 0); - D3dpp.Windowed = TRUE; - InterlockedExchange(&ddraw->resetDirect3D9, TRUE); + InterlockedExchange(&ddraw->minimized, TRUE); } } return 0; @@ -1254,8 +1255,8 @@ HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnk DWORD minor = (DWORD)(HIBYTE(LOWORD(version))); LPDIRECT3D9 d3d = NULL; - // Win Vista/XP use Direct3D 9 - Win 7/8/10 and wine use OpenGL - if (!This->wine && (major < 6 || (major == 6 && minor == 0)) && (hD3D9 = LoadLibrary("d3d9.dll"))) + // Win XP/Vista/7 use Direct3D 9 - Win 8/10 and wine use OpenGL + if (!This->wine && (major < 6 || (major == 6 && minor == 1)) && (hD3D9 = LoadLibrary("d3d9.dll"))) { IDirect3D9 *(WINAPI *D3DCreate9)(UINT) = (IDirect3D9 *(WINAPI *)(UINT))GetProcAddress(hD3D9, "Direct3DCreate9"); diff --git a/src/render_d3d9.c b/src/render_d3d9.c index 7684d3a..c2b6538 100644 --- a/src/render_d3d9.c +++ b/src/render_d3d9.c @@ -9,6 +9,8 @@ typedef struct CUSTOMVERTEX { float x, y, z, rhw, u, v; } CUSTOMVERTEX; HMODULE hD3D9; D3DPRESENT_PARAMETERS D3dpp; +BOOL UseDirect3D9; + static LPDIRECT3D9 D3d; static LPDIRECT3DDEVICE9 D3ddev; static LPDIRECT3DVERTEXBUFFER9 D3dvb; @@ -22,10 +24,10 @@ static DWORD FrameLength; static BOOL CreateDirect3D(); static BOOL CreateResources(); -static void SetStates(); +static BOOL SetStates(); static void UpdateVertices(BOOL inCutscene); static BOOL Reset(); -static void SetMaxFPS(int baseMaxFPS); +static void SetMaxFPS(); static void Render(); static BOOL ReleaseDirect3D(); @@ -36,18 +38,17 @@ DWORD WINAPI render_d3d9_main(void) { Sleep(500); - BOOL useDirect3D = CreateDirect3D() && CreateResources(); - if (useDirect3D) + UseDirect3D9 = CreateDirect3D(); + if (UseDirect3D9) { - SetMaxFPS(ddraw->render.maxfps); - SetStates(); + SetMaxFPS(); Render(); } ReleaseDirect3D(); - if (!useDirect3D) + if (!UseDirect3D9) { ShowDriverWarning = TRUE; ddraw->renderer = render_soft_main; @@ -76,8 +77,8 @@ static BOOL CreateDirect3D() D3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; D3dpp.hDeviceWindow = ddraw->hWnd; D3dpp.PresentationInterval = ddraw->vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; - D3dpp.BackBufferWidth = ddraw->render.width; - D3dpp.BackBufferHeight = ddraw->render.height; + D3dpp.BackBufferWidth = D3dpp.Windowed ? 0 : ddraw->render.width; + D3dpp.BackBufferHeight = D3dpp.Windowed ? 0 : ddraw->render.height; D3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; D3dpp.BackBufferCount = 1; @@ -105,7 +106,7 @@ static BOOL CreateDirect3D() } } - return D3d && D3ddev; + return D3d && D3ddev && CreateResources() && SetStates(); } static BOOL CreateResources() @@ -135,13 +136,15 @@ static BOOL CreateResources() return SurfaceTex && PaletteTex && D3dvb && PixelShader; } -static void SetStates() +static BOOL SetStates() { - D3ddev->lpVtbl->SetFVF(D3ddev, D3DFVF_XYZRHW | D3DFVF_TEX1); - D3ddev->lpVtbl->SetStreamSource(D3ddev, 0, D3dvb, 0, sizeof(CUSTOMVERTEX)); - D3ddev->lpVtbl->SetTexture(D3ddev, 0, (IDirect3DBaseTexture9 *)SurfaceTex); - D3ddev->lpVtbl->SetTexture(D3ddev, 1, (IDirect3DBaseTexture9 *)PaletteTex); - D3ddev->lpVtbl->SetPixelShader(D3ddev, PixelShader); + BOOL err = FALSE; + + err = err || FAILED(D3ddev->lpVtbl->SetFVF(D3ddev, D3DFVF_XYZRHW | D3DFVF_TEX1)); + err = err || FAILED(D3ddev->lpVtbl->SetStreamSource(D3ddev, 0, D3dvb, 0, sizeof(CUSTOMVERTEX))); + err = err || FAILED(D3ddev->lpVtbl->SetTexture(D3ddev, 0, (IDirect3DBaseTexture9 *)SurfaceTex)); + err = err || FAILED(D3ddev->lpVtbl->SetTexture(D3ddev, 1, (IDirect3DBaseTexture9 *)PaletteTex)); + err = err || FAILED(D3ddev->lpVtbl->SetPixelShader(D3ddev, PixelShader)); D3DVIEWPORT9 viewData = { ddraw->render.viewport.x, @@ -151,7 +154,9 @@ static void SetStates() 0.0f, 1.0f }; - D3ddev->lpVtbl->SetViewport(D3ddev, &viewData); + err = err || FAILED(D3ddev->lpVtbl->SetViewport(D3ddev, &viewData)); + + return !err; } static void UpdateVertices(BOOL inCutscene) @@ -183,18 +188,19 @@ static void UpdateVertices(BOOL inCutscene) static BOOL Reset() { + D3dpp.BackBufferWidth = D3dpp.Windowed ? 0 : ddraw->render.width; + D3dpp.BackBufferHeight = D3dpp.Windowed ? 0 : ddraw->render.height; + D3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; + if (SUCCEEDED(D3ddev->lpVtbl->Reset(D3ddev, &D3dpp))) - { - SetStates(); - return TRUE; - } + return SetStates(); return FALSE; } -static void SetMaxFPS(int baseMaxFPS) +static void SetMaxFPS() { - MaxFPS = baseMaxFPS; + MaxFPS = ddraw->render.maxfps; if (MaxFPS < 0) MaxFPS = ddraw->mode.dmDisplayFrequency; @@ -213,9 +219,19 @@ static void Render() { DWORD tick_start = 0; DWORD tick_end = 0; + BOOL active = TRUE; while (ddraw->render.run && WaitForSingleObject(ddraw->render.sem, 200) != WAIT_FAILED) { + if (!active) + { + if (!InterlockedExchangeAdd(&ddraw->minimized, 0) && CreateDirect3D()) + active = TRUE; + + Sleep(500); + continue; + } + #if _DEBUG DrawFrameInfoStart(); #endif @@ -282,7 +298,14 @@ static void Render() HRESULT hr = D3ddev->lpVtbl->TestCooperativeLevel(D3ddev); - if (InterlockedExchange(&ddraw->resetDirect3D9, FALSE)) + if (InterlockedExchangeAdd(&ddraw->minimized, 0)) + { + active = FALSE; + ReleaseDirect3D(); + Sleep(200); + ShowWindow(ddraw->hWnd, SW_SHOWMINNOACTIVE); + } + else if (InterlockedExchange(&ddraw->resetDirect3D9, FALSE)) { Reset(); }