Skip to content

Commit

Permalink
Remove Reset() from CreateD9Device()
Browse files Browse the repository at this point in the history
  • Loading branch information
elishacloud committed Oct 2, 2024
1 parent 81eb422 commit 75ed1d6
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 153 deletions.
2 changes: 1 addition & 1 deletion Dllmain/BuildNo.rc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define BUILD_NUMBER 7228
#define BUILD_NUMBER 7229
20 changes: 7 additions & 13 deletions GDI/WndProc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,7 @@ LRESULT CALLBACK WndProc::Handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPa

const WNDPROC pWndProc = AppWndProcInstance->GetAppWndProc();
const HWND hWndInstance = AppWndProcInstance->GetHWnd();
#ifdef _DEBUG
DATASTRUCT* pDataStruct = AppWndProcInstance->GetDataStruct();
#endif

// Set instance as inactive when window closes
if ((Msg == WM_CLOSE || Msg == WM_DESTROY || Msg == WM_NCDESTROY || (Msg == WM_SYSCOMMAND && wParam == SC_CLOSE)) && hWnd == hWndInstance)
Expand Down Expand Up @@ -272,21 +270,17 @@ LRESULT CALLBACK WndProc::Handler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPa
// Special handling for DirectDraw games
if (AppWndProcInstance->IsDirectDraw())
{
#ifdef _DEBUG
if (Msg == WM_ACTIVATE)
// Filter some messages while creating a Direct3D9 device
if (pDataStruct->IsCreatingD3d9)
{
WORD lwParam = LOWORD(wParam);

bool LastActived = pDataStruct->IsWindowActivated;
pDataStruct->IsWindowActivated = (lwParam == WA_ACTIVE || lwParam == WA_CLICKACTIVE) ? true : (lwParam == WA_INACTIVE) ? false : LastActived;

// Filter some WM_ACTIVATE calls, some games don't handle invalid calls well
if (pDataStruct->IsCreatingD3d9)
switch (Msg)
{
//return NULL;
case WM_NCACTIVATE:
return TRUE;
case WM_ACTIVATE:
return NULL;
}
}
#endif
// Some games hang when attempting to paint while iconic
if ((Msg == WM_PAINT || Msg == WM_SYNCPAINT) && IsIconic(hWnd))
{
Expand Down
1 change: 0 additions & 1 deletion GDI/WndProc.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ bool CheckDirectDrawXInterface(void* pInterface);
namespace WndProc
{
struct DATASTRUCT {
std::atomic<bool> IsWindowActivated = false;
std::atomic<bool> IsCreatingD3d9 = false;
};

Expand Down
4 changes: 2 additions & 2 deletions ddraw/IDirectDrawSurfaceX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3055,7 +3055,7 @@ HRESULT m_IDirectDrawSurfaceX::Restore()
switch (ddrawParent->TestD3D9CooperativeLevel())
{
case D3DERR_DEVICENOTRESET:
if (FAILED(ddrawParent->ReinitDevice()))
if (FAILED(ddrawParent->ResetD9Device()))
{
return DDERR_WRONGMODE;
}
Expand Down Expand Up @@ -4273,7 +4273,7 @@ HRESULT m_IDirectDrawSurfaceX::CheckInterface(char *FunctionName, bool CheckD3DD
case DDERR_NOEXCLUSIVEMODE:
break;
case D3DERR_DEVICENOTRESET:
if (SUCCEEDED(ddrawParent->ReinitDevice()))
if (SUCCEEDED(ddrawParent->ResetD9Device()))
{
break;
}
Expand Down
227 changes: 92 additions & 135 deletions ddraw/IDirectDrawX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2179,7 +2179,7 @@ HRESULT m_IDirectDrawX::RestoreAllSurfaces()
HRESULT hr = TestD3D9CooperativeLevel();
if (hr == D3DERR_DEVICENOTRESET)
{
hr = ReinitDevice();
hr = ResetD9Device();
}

// Check device status
Expand Down Expand Up @@ -2917,21 +2917,81 @@ HRESULT m_IDirectDrawX::ResetD9Device()
{
Logging::LogDebug() << __FUNCTION__ << " (" << this << ")";

// Prepare for reset
ReleaseAllD9Resources(true, true);
// Check for device interface
if (FAILED(CheckInterface(__FUNCTION__, true)))
{
return DDERR_WRONGMODE;
}

// Reset device. When this method returns: BackBufferCount, BackBufferWidth, and BackBufferHeight are set to zero.
D3DPRESENT_PARAMETERS newParams = presParams;
HRESULT hr = d3d9Device->Reset(&newParams);
// Check if device is ready to be restored
HRESULT hr = TestD3D9CooperativeLevel();
if (SUCCEEDED(hr) || hr == DDERR_NOEXCLUSIVEMODE)
{
return hr;
}
else if (hr == D3DERR_DEVICELOST)
{
HWND hWnd = GetHwnd();
if (!IsIconic(hWnd) && hWnd == GetForegroundWindow())
{
return DDERR_WRONGMODE;
}
else
{
return DDERR_SURFACELOST;
}
}
else if (hr != D3DERR_DEVICENOTRESET)
{
LOG_LIMIT(100, __FUNCTION__ << " Error: TestCooperativeLevel = " << (D3DERR)hr);
return DDERR_WRONGMODE;
}

// If Reset fails then release the device and all resources
if (FAILED(hr))
SetCriticalSection();
SetPTCriticalSection();

// Reset device if current thread matches creation thread
if (IsWindow(hFocusWindow) && GetWindowThreadProcessId(hFocusWindow, nullptr) == GetCurrentThreadId())
{
// Prepare for reset
ReleaseAllD9Resources(true, true);

// Reset device. When this method returns: BackBufferCount, BackBufferWidth, and BackBufferHeight are set to zero.
D3DPRESENT_PARAMETERS newParams = presParams;
hr = d3d9Device->Reset(&newParams);

// If Reset fails then release the device and all resources
if (FAILED(hr))
{
LOG_LIMIT(100, __FUNCTION__ << " Error: Reset failed: " << (D3DERR)hr);
ReleaseAllD9Resources(false, false); // Cannot backup surface after a failed Reset
ReleaseD9Device();
hr = CreateD9Device(__FUNCTION__);
}
else
{
// Reset render target
ReSetRenderTarget();

// Reset D3D device settings
if (D3DDeviceInterface)
{
D3DDeviceInterface->ResetDevice();
}
}
}
// Release and recreate device
else
{
LOG_LIMIT(100, __FUNCTION__ << " Error: Reset failed " << (D3DERR)hr);
ReleaseAllD9Resources(false, false); // Cannot backup surface after a failed Reset
ReleaseAllD9Resources(true, false);
ReleaseD9Device();
hr = CreateD9Device(__FUNCTION__);
}

ReleasePTCriticalSection();
ReleaseCriticalSection();

// Return
return hr;
}

Expand All @@ -2955,9 +3015,7 @@ HRESULT m_IDirectDrawX::CreateD9Device(char* FunctionName)
SetCriticalSection();
SetPTCriticalSection();

#ifdef _DEBUG
WndProc::DATASTRUCT* WndDataStruct = nullptr;
#endif

HRESULT hr = DD_OK;
do {
Expand All @@ -2973,7 +3031,10 @@ HRESULT m_IDirectDrawX::CreateD9Device(char* FunctionName)
hFocusWindow = hWnd;

// Hook WndProc before creating device
WndProc::AddWndProc(hWnd, true);
bool WndProcAdded = WndProc::AddWndProc(hWnd, true);

// Get wndproc structure
WndDataStruct = WndProc::GetWndProctStruct(hWnd);

// Get current resolution and rect
DWORD CurrentWidth = 0, CurrentHeight = 0;
Expand Down Expand Up @@ -3105,29 +3166,19 @@ HRESULT m_IDirectDrawX::CreateD9Device(char* FunctionName)
break;
}

// Try to reset existing device
hr = TestD3D9CooperativeLevel();
if (LastHWnd == hWnd && LastBehaviorFlags == BehaviorFlags && // Device arguments are not changed
(SUCCEEDED(hr) || hr == DDERR_NOEXCLUSIVEMODE || hr == D3DERR_DEVICENOTRESET) && // Device is ready to be reset
(IsWindow(hWnd) && GetWindowThreadProcessId(hWnd, nullptr) != GetCurrentThreadId())) // Calling thread matches current thread
{
hr = ResetD9Device();
}
// Release existing device
else
{
Logging::Log() << __FUNCTION__ << " Recreate device! Last create: " << LastHWnd << "->" << hWnd << " " <<
" Windowed: " << LastWindowedMode << "->" << presParams.Windowed << " " <<
Logging::hex(LastBehaviorFlags) << "->" << Logging::hex(BehaviorFlags);
Logging::Log() << __FUNCTION__ << " Recreate device! Last create: " << LastHWnd << "->" << hWnd << " " <<
" Windowed: " << LastWindowedMode << "->" << presParams.Windowed << " " <<
presParamsBackup.BackBufferWidth << "x" << presParamsBackup.BackBufferHeight << "->" <<
presParams.BackBufferWidth << "x" << presParams.BackBufferHeight << " " <<
Logging::hex(LastBehaviorFlags) << "->" << Logging::hex(BehaviorFlags);

ReleaseAllD9Resources(true, false);
ReleaseD9Device();
ReleaseAllD9Resources(true, false);
ReleaseD9Device();

// Reset display mode after release when display mode is already setup and there is a primary surface
if (presParams.Windowed && PrimarySurface && DisplayMode.Width == CurrentWidth && DisplayMode.Height == CurrentHeight)
{
Utils::SetDisplaySettings(hWnd, DisplayMode.Width, DisplayMode.Height);
}
// Reset display mode after release when display mode is already setup and there is a primary surface
if (presParams.Windowed && PrimarySurface && DisplayMode.Width == CurrentWidth && DisplayMode.Height == CurrentHeight)
{
Utils::SetDisplaySettings(hWnd, DisplayMode.Width, DisplayMode.Height);
}
}

Expand All @@ -3140,20 +3191,13 @@ HRESULT m_IDirectDrawX::CreateD9Device(char* FunctionName)
Utils::SetDisplaySettings(hWnd, presParams.BackBufferWidth, presParams.BackBufferHeight);

SetWindowPos(hWnd, ((GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP),
0, 0, presParams.BackBufferWidth, presParams.BackBufferHeight, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOREPOSITION | SWP_NOMOVE | SWP_NOREDRAW);
0, 0, presParams.BackBufferWidth, presParams.BackBufferHeight, SWP_NOZORDER | SWP_NOMOVE);
}

#ifdef _DEBUG
// Get wndproc structure
WndDataStruct = WndProc::GetWndProctStruct(hWnd);
if (WndDataStruct)
{
WndDataStruct->IsCreatingD3d9 = true;
}
#endif
if (WndDataStruct) WndDataStruct->IsCreatingD3d9 = true;

// Check window handle thread
if (IsWindow(hWnd) && GetWindowThreadProcessId(hWnd, nullptr) != GetCurrentThreadId())
if (WndProcAdded && GetWindowThreadProcessId(hWnd, nullptr) != GetCurrentThreadId())
{
LOG_LIMIT(100, __FUNCTION__ << " " << FunctionName << " Warning: trying to create Direct3D9 device from a different thread than the hwnd was created from!");

Expand All @@ -3174,7 +3218,7 @@ HRESULT m_IDirectDrawX::CreateD9Device(char* FunctionName)
DeviceStruct.presParams = &presParams;
DeviceStruct.hEvent = hEvent;

PostMessageA(hWnd, WM_USER_CREATE_D3D9_DEVICE, (WPARAM)this, (LPARAM)&DeviceStruct);
PostMessage(hWnd, WM_USER_CREATE_D3D9_DEVICE, (WPARAM)this, (LPARAM)&DeviceStruct);
WaitForSingleObject(hEvent, INFINITE);

hr = DeviceStruct.hr;
Expand All @@ -3186,13 +3230,7 @@ HRESULT m_IDirectDrawX::CreateD9Device(char* FunctionName)
hr = d3d9Object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, BehaviorFlags, &presParams, &d3d9Device);
}

#ifdef _DEBUG
// Unset flag
if (WndDataStruct)
{
WndDataStruct->IsCreatingD3d9 = false;
}
#endif
if (WndDataStruct) WndDataStruct->IsCreatingD3d9 = false;
}

if (FAILED(hr))
Expand Down Expand Up @@ -3262,13 +3300,7 @@ HRESULT m_IDirectDrawX::CreateD9Device(char* FunctionName)

} while (false);

#ifdef _DEBUG
// Unset flag
if (WndDataStruct)
{
WndDataStruct->IsCreatingD3d9 = false;
}
#endif
if (WndDataStruct) WndDataStruct->IsCreatingD3d9 = false;

ReleasePTCriticalSection();
ReleaseCriticalSection();
Expand Down Expand Up @@ -3444,81 +3476,6 @@ HRESULT m_IDirectDrawX::CreateD9Object()
return D3D_OK;
}

// Reinitialize d3d9 device
HRESULT m_IDirectDrawX::ReinitDevice()
{
Logging::LogDebug() << __FUNCTION__ << " (" << this << ")";

// Check for device interface
if (FAILED(CheckInterface(__FUNCTION__, true)))
{
return DDERR_WRONGMODE;
}

// Check if device is ready to be restored
HRESULT hr = TestD3D9CooperativeLevel();
if (SUCCEEDED(hr) || hr == DDERR_NOEXCLUSIVEMODE)
{
return hr;
}
else if (hr == D3DERR_DEVICELOST)
{
HWND hWnd = GetHwnd();
if (!IsIconic(hWnd) && hWnd == GetForegroundWindow())
{
return DDERR_WRONGMODE;
}
else
{
return DDERR_SURFACELOST;
}
}
else if (hr != D3DERR_DEVICENOTRESET)
{
LOG_LIMIT(100, __FUNCTION__ << " Error: TestCooperativeLevel = " << (D3DERR)hr);
return DDERR_WRONGMODE;
}

SetCriticalSection();
SetPTCriticalSection();

// Reset device if current thread matches creation thread
if (IsWindow(hFocusWindow) && GetWindowThreadProcessId(hFocusWindow, nullptr) == GetCurrentThreadId())
{
hr = ResetD9Device();

if (SUCCEEDED(hr))
{
// Reset render target
ReSetRenderTarget();

// Reset D3D device settings
if (D3DDeviceInterface)
{
D3DDeviceInterface->ResetDevice();
}
}
// Try to recreate the device
else
{
hr = CreateD9Device(__FUNCTION__);
}
}
// Release and recreate device
else
{
ReleaseAllD9Resources(true, false);
ReleaseD9Device();
hr = CreateD9Device(__FUNCTION__);
}

ReleasePTCriticalSection();
ReleaseCriticalSection();

// Return
return hr;
}

HRESULT m_IDirectDrawX::TestD3D9CooperativeLevel()
{
if (d3d9Device)
Expand Down Expand Up @@ -4689,7 +4646,7 @@ HRESULT m_IDirectDrawX::Present(RECT* pSourceRect, RECT* pDestRect)
// Reset device
if (hr == D3DERR_DEVICENOTRESET)
{
hr = ReinitDevice();
hr = ResetD9Device();
}

// Present failure
Expand Down
1 change: 0 additions & 1 deletion ddraw/IDirectDrawX.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ class m_IDirectDrawX : public IUnknown, public AddressLookupTableDdrawObject
HRESULT ResetD9Device();
HRESULT CreateD9Device(char* FunctionName);
HRESULT CreateVertexBuffer(DWORD Width, DWORD Height);
HRESULT ReinitDevice();
HRESULT TestD3D9CooperativeLevel();

// Device information functions
Expand Down

0 comments on commit 75ed1d6

Please sign in to comment.