diff --git a/ddraw.rc b/ddraw.rc index bf02e50..538ae17 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,1,1 +#define VERSION 1,2,1,2 1 VERSIONINFO FILEVERSION VERSION diff --git a/inc/main.h b/inc/main.h index a29e9f5..aaef0e9 100644 --- a/inc/main.h +++ b/inc/main.h @@ -26,7 +26,7 @@ #define WM_AUTORENDERER WM_USER+111 #define WM_WINEFULLSCREEN WM_USER+112 -#define WM_D3D9FULLSCREEN WM_USER+113 +#define WM_D3D9DEVICELOST WM_USER+113 extern BOOL ShowDriverWarning; @@ -99,7 +99,6 @@ typedef struct IDirectDrawImpl char shader[MAX_PATH]; BOOL wine; int sleep; - LONG displayModeChanged; LONG minimized; } IDirectDrawImpl; diff --git a/src/main.c b/src/main.c index 4a2c5db..cae43c1 100644 --- a/src/main.c +++ b/src/main.c @@ -38,9 +38,13 @@ void mouse_unlock(); BOOL screenshot(struct IDirectDrawSurfaceImpl *); #endif -extern BOOL D3D9_Enabled; extern HMODULE D3D9_hModule; +BOOL CreateDirect3D9(); +BOOL ResetDirect3D9(); +BOOL ReleaseDirect3D9(); +BOOL DeviceLostDirect3D9(); + IDirectDrawImpl *ddraw = NULL; DWORD WINAPI render_main(void); @@ -51,6 +55,7 @@ DWORD WINAPI render_d3d9_main(void); int WindowPosX; int WindowPosY; char SettingsIniPath[MAX_PATH]; +BOOL Direct3D9Active; //BOOL WINAPI DllMainCRTStartup(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved) BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) @@ -226,7 +231,7 @@ HRESULT __stdcall ddraw_RestoreDisplayMode(IDirectDrawImpl *This) } /* only stop drawing in GL mode when minimized */ - if (This->renderer == render_main) + if (This->renderer != render_soft_main) { EnterCriticalSection(&This->cs); This->render.run = FALSE; @@ -235,19 +240,31 @@ HRESULT __stdcall ddraw_RestoreDisplayMode(IDirectDrawImpl *This) WaitForSingleObject(This->render.thread, INFINITE); This->render.thread = NULL; + + if (This->renderer == render_d3d9_main) + ReleaseDirect3D9(); } if(!ddraw->windowed) { - if (!D3D9_Enabled) + if (!Direct3D9Active) ChangeDisplaySettings(&This->mode, 0); - - InterlockedExchange(&ddraw->minimized, TRUE); } return DD_OK; } +void InitDirect3D9() +{ + Direct3D9Active = CreateDirect3D9(); + if (!Direct3D9Active) + { + ReleaseDirect3D9(); + ShowDriverWarning = TRUE; + ddraw->renderer = render_soft_main; + } +} + HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD height, DWORD bpp) { printf("DirectDraw::SetDisplayMode(This=%p, width=%d, height=%d, bpp=%d)\n", This, (unsigned int)width, (unsigned int)height, (unsigned int)bpp); @@ -448,14 +465,23 @@ HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD SetWindowPos(ddraw->hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); MoveWindow(This->hWnd, dst.left, dst.top, (dst.right - dst.left), (dst.bottom - dst.top), TRUE); This->windowed_init = TRUE; + + if (This->renderer == render_d3d9_main) + InitDirect3D9(); } } else { - if(!This->devmode && ChangeDisplaySettings(&This->render.mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + if (This->renderer == render_d3d9_main) + InitDirect3D9(); + + if(!This->devmode) { - This->render.run = FALSE; - return DDERR_INVALIDMODE; + if (!Direct3D9Active && ChangeDisplaySettings(&This->render.mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + { + This->render.run = FALSE; + return DDERR_INVALIDMODE; + } } if (ddraw->wine) @@ -522,7 +548,7 @@ void ToggleFullscreen() if (ddraw->windowed) { mouse_unlock(); - if(ChangeDisplaySettings(&ddraw->render.mode, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL) + if(ChangeDisplaySettings(&ddraw->render.mode, CDS_TEST) == DISP_CHANGE_SUCCESSFUL) { ddraw->windowed = FALSE; @@ -530,15 +556,17 @@ void ToggleFullscreen() SetWindowPos(ddraw->hWnd, HWND_TOPMOST, 0, 0, ddraw->render.width, ddraw->render.height, SWP_SHOWWINDOW); LastSetWindowPosTick = timeGetTime(); - InterlockedExchange(&ddraw->displayModeChanged, TRUE); + if (Direct3D9Active) + ResetDirect3D9(); + else + ChangeDisplaySettings(&ddraw->render.mode, CDS_FULLSCREEN); } mouse_lock(); } else { mouse_unlock(); - InterlockedExchange(&ddraw->displayModeChanged, TRUE); - if(D3D9_Enabled || ChangeDisplaySettings(&ddraw->mode, 0) == DISP_CHANGE_SUCCESSFUL) + if(Direct3D9Active || ChangeDisplaySettings(&ddraw->mode, 0) == DISP_CHANGE_SUCCESSFUL) { if (!ddraw->border) { @@ -559,8 +587,11 @@ void ToggleFullscreen() ddraw->windowed = TRUE; ddraw->windowed_init = TRUE; - InterlockedExchange(&ddraw->displayModeChanged, TRUE); + + if (Direct3D9Active) + ResetDirect3D9(); } + mouse_lock(); } } @@ -570,13 +601,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) switch(uMsg) { - case WM_D3D9FULLSCREEN: + case WM_D3D9DEVICELOST: { - if (!ddraw->windowed) + if (Direct3D9Active && DeviceLostDirect3D9()) { - if (GetSystemMetrics(SM_CYSCREEN) == ddraw->render.mode.dmPelsHeight && - GetSystemMetrics(SM_CXSCREEN) == ddraw->render.mode.dmPelsWidth && - GetForegroundWindow() == ddraw->hWnd) + if (!ddraw->windowed) mouse_lock(); } return 0; @@ -639,7 +668,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (!ddraw->windowed) { - if (!D3D9_Enabled) + if (!Direct3D9Active) { ChangeDisplaySettings(&ddraw->render.mode, CDS_FULLSCREEN); @@ -662,7 +691,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) /* minimize our window on defocus when in fullscreen */ if (!ddraw->windowed) { - if (!D3D9_Enabled) + if (!Direct3D9Active) { ShowWindow(ddraw->hWnd, SW_MINIMIZE); ChangeDisplaySettings(&ddraw->mode, 0); @@ -944,6 +973,9 @@ ULONG __stdcall ddraw_Release(IDirectDrawImpl *This) WaitForSingleObject(This->render.thread, INFINITE); This->render.thread = NULL; + + if (This->renderer == render_d3d9_main) + ReleaseDirect3D9(); } if(This->render.hDC) diff --git a/src/render_d3d9.c b/src/render_d3d9.c index f52121b..2a01919 100644 --- a/src/render_d3d9.c +++ b/src/render_d3d9.c @@ -7,7 +7,6 @@ typedef struct CUSTOMVERTEX { float x, y, z, rhw, u, v; } CUSTOMVERTEX; -BOOL D3D9_Enabled; HMODULE D3D9_hModule; static D3DPRESENT_PARAMETERS D3dpp; @@ -23,14 +22,16 @@ static int MaxFPS; static DWORD FrameLength; static int BitsPerPixel; -static BOOL CreateDirect3D(); static BOOL CreateResources(); static BOOL SetStates(); static BOOL UpdateVertices(BOOL inCutscene); -static BOOL Reset(); static void SetMaxFPS(); static void Render(); -static BOOL ReleaseDirect3D(); + +BOOL CreateDirect3D9(); +BOOL ResetDirect3D9(); +BOOL ReleaseDirect3D9(); +BOOL DeviceLostDirect3D9(); BOOL detect_cutscene(); DWORD WINAPI render_soft_main(void); @@ -39,29 +40,15 @@ DWORD WINAPI render_d3d9_main(void) { Sleep(500); - D3D9_Enabled = CreateDirect3D(); - if (D3D9_Enabled) - { - SetMaxFPS(); - - Render(); - } - - ReleaseDirect3D(); - - if (!D3D9_Enabled) - { - ShowDriverWarning = TRUE; - ddraw->renderer = render_soft_main; - render_soft_main(); - } + SetMaxFPS(); + Render(); return 0; } -static BOOL CreateDirect3D() +BOOL CreateDirect3D9() { - if (!ReleaseDirect3D()) + if (!ReleaseDirect3D9()) return FALSE; if (!D3D9_hModule) @@ -102,7 +89,7 @@ static BOOL CreateDirect3D() D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, ddraw->hWnd, - D3DCREATE_MULTITHREADED | D3DCREATE_NOWINDOWCHANGES | behaviorFlags[i], + D3DCREATE_MULTITHREADED | behaviorFlags[i], //D3DCREATE_NOWINDOWCHANGES | &D3dpp, &D3dDev))) return D3dDev && CreateResources() && SetStates(); @@ -203,8 +190,17 @@ static BOOL UpdateVertices(BOOL inCutscene) return FALSE; } -static BOOL Reset() +BOOL DeviceLostDirect3D9() { + if (D3dDev && D3dDev->lpVtbl->TestCooperativeLevel(D3dDev) == D3DERR_DEVICENOTRESET) + return ResetDirect3D9(); + + return FALSE; +} + +BOOL ResetDirect3D9() +{ + D3dpp.Windowed = ddraw->windowed; D3dpp.BackBufferWidth = D3dpp.Windowed ? 0 : ddraw->render.width; D3dpp.BackBufferHeight = D3dpp.Windowed ? 0 : ddraw->render.height; D3dpp.BackBufferFormat = BitsPerPixel == 16 ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8; @@ -236,25 +232,12 @@ static void Render() { DWORD tickStart = 0; DWORD tickEnd = 0; - BOOL active = TRUE; - BOOL released = TRUE; - LONG minimized = TRUE; while (ddraw->render.run && WaitForSingleObject(ddraw->render.sem, 200) != WAIT_FAILED) { - if (!active) + if (InterlockedExchangeAdd(&ddraw->minimized, 0)) { Sleep(500); - - if (!released && (released = ReleaseDirect3D()) && minimized) - ShowWindow(ddraw->hWnd, SW_MINIMIZE); - - if (!InterlockedExchangeAdd(&ddraw->minimized, 0) && CreateDirect3D()) - { - active = TRUE; - PostMessage(ddraw->hWnd, WM_D3D9FULLSCREEN, 0, 0); - } - continue; } @@ -322,29 +305,14 @@ static void Render() LeaveCriticalSection(&ddraw->cs); - HRESULT hr = D3dDev->lpVtbl->TestCooperativeLevel(D3dDev); - LONG modeChanged = InterlockedExchange(&ddraw->displayModeChanged, FALSE); - minimized = InterlockedExchangeAdd(&ddraw->minimized, 0); + D3dDev->lpVtbl->BeginScene(D3dDev); + D3dDev->lpVtbl->DrawPrimitive(D3dDev, D3DPT_TRIANGLESTRIP, 0, 2); + D3dDev->lpVtbl->EndScene(D3dDev); - if (minimized || modeChanged) + if (D3dDev->lpVtbl->Present(D3dDev, NULL, NULL, NULL, NULL) == D3DERR_DEVICELOST) { - active = FALSE; - released = ReleaseDirect3D(); - - if (released && minimized) - ShowWindow(ddraw->hWnd, SW_MINIMIZE); - } - else if (hr == D3DERR_DEVICENOTRESET && D3dpp.Windowed) - { - Reset(); - } - else if (SUCCEEDED(hr)) - { - D3dDev->lpVtbl->BeginScene(D3dDev); - D3dDev->lpVtbl->DrawPrimitive(D3dDev, D3DPT_TRIANGLESTRIP, 0, 2); - D3dDev->lpVtbl->EndScene(D3dDev); - - D3dDev->lpVtbl->Present(D3dDev, NULL, NULL, NULL, NULL); + DWORD_PTR dwResult; + SendMessageTimeout(ddraw->hWnd, WM_D3D9DEVICELOST, 0, 0, 0, 1000, &dwResult); } #if _DEBUG @@ -361,7 +329,7 @@ static void Render() } } -static BOOL ReleaseDirect3D() +BOOL ReleaseDirect3D9() { if (VertexBuf) {