diff --git a/src/d3d9/d3d9_cursor.cpp b/src/d3d9/d3d9_cursor.cpp index 66751029d..b7993e5e5 100644 --- a/src/d3d9/d3d9_cursor.cpp +++ b/src/d3d9/d3d9_cursor.cpp @@ -9,15 +9,22 @@ namespace dxvk { void D3D9Cursor::ResetCursor() { ShowCursor(FALSE); - if (likely(m_hCursor != nullptr)) { - ::DestroyCursor(m_hCursor); - m_hCursor = nullptr; - } else { - m_sCursor.Width = 0; - m_sCursor.Height = 0; - m_sCursor.X = 0; - m_sCursor.Y = 0; - } + if (m_hCursor != nullptr) + ResetHardwareCursor(); + else + ResetSoftwareCursor(); + } + + + void D3D9Cursor::ResetHardwareCursor() { + ::DestroyCursor(m_hCursor); + m_hCursor = nullptr; + } + + + void D3D9Cursor::ResetSoftwareCursor() { + m_sCursor.DrawCursor = false; + m_sCursor.ResetCursor = true; } @@ -44,20 +51,18 @@ namespace dxvk { if (unlikely(m_hCursor == nullptr && m_sCursor.Width == 0 && m_sCursor.Height == 0)) return m_visible; - if (likely(m_hCursor != nullptr)) + if (m_hCursor != nullptr) ::SetCursor(bShow ? m_hCursor : nullptr); + else + m_sCursor.DrawCursor = bShow; return std::exchange(m_visible, bShow); } HRESULT D3D9Cursor::SetHardwareCursor(UINT XHotSpot, UINT YHotSpot, const CursorBitmap& bitmap) { - if (unlikely(IsSoftwareCursor())) { - m_sCursor.Width = 0; - m_sCursor.Height = 0; - m_sCursor.X = 0; - m_sCursor.Y = 0; - } + if (IsSoftwareCursor()) + ResetSoftwareCursor(); CursorMask mask; std::memset(mask, ~0, sizeof(mask)); @@ -87,10 +92,8 @@ namespace dxvk { // Make sure to hide the win32 cursor ::SetCursor(nullptr); - if (unlikely(m_hCursor != nullptr)) { - ::DestroyCursor(m_hCursor); - m_hCursor = nullptr; - } + if (m_hCursor != nullptr) + ResetHardwareCursor(); m_sCursor.Width = Width; m_sCursor.Height = Height; @@ -107,6 +110,13 @@ namespace dxvk { Logger::warn("D3D9Cursor::ResetCursor: Not supported on current platform."); } + void D3D9Cursor::ResetHardwareCursor() { + Logger::warn("D3D9Cursor::ResetHardwareCursor: Not supported on current platform."); + } + + void D3D9Cursor::ResetSoftwareCursor() { + Logger::warn("D3D9Cursor::ResetSoftwareCursor: Not supported on current platform."); + } void D3D9Cursor::UpdateCursor(int X, int Y) { Logger::warn("D3D9Cursor::UpdateCursor: Not supported on current platform."); diff --git a/src/d3d9/d3d9_cursor.h b/src/d3d9/d3d9_cursor.h index b2b858a3c..af96884be 100644 --- a/src/d3d9/d3d9_cursor.h +++ b/src/d3d9/d3d9_cursor.h @@ -8,10 +8,12 @@ namespace dxvk { * \brief D3D9 Software Cursor */ struct D3D9_SOFTWARE_CURSOR { - UINT Width = 0; + UINT Width = 0; UINT Height = 0; UINT X = 0; UINT Y = 0; + bool DrawCursor = false; + bool ResetCursor = false; }; constexpr uint32_t HardwareCursorWidth = 32u; @@ -37,6 +39,10 @@ namespace dxvk { void ResetCursor(); + void ResetHardwareCursor(); + + void ResetSoftwareCursor(); + void UpdateCursor(int X, int Y); void RefreshSoftwareCursorPosition(); diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index cc8206058..74711972d 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -3917,11 +3917,22 @@ namespace dxvk { D3D9_SOFTWARE_CURSOR* pSoftwareCursor = m_cursor.GetSoftwareCursor(); - UINT cursorWidth = m_cursor.IsCursorVisible() ? pSoftwareCursor->Width : 0; - UINT cursorHeight = m_cursor.IsCursorVisible() ? pSoftwareCursor->Height : 0; + UINT cursorWidth = pSoftwareCursor->DrawCursor ? pSoftwareCursor->Width : 0; + UINT cursorHeight = pSoftwareCursor->DrawCursor ? pSoftwareCursor->Height : 0; m_implicitSwapchain->SetCursorPosition(pSoftwareCursor->X, pSoftwareCursor->Y, cursorWidth, cursorHeight); + + // Once a hardware cursor has been set or the device has been reset, + // we need to ensure that we render a 0-sized rectangle first, and + // only then fully clear the software cursor. + if (unlikely(pSoftwareCursor->ResetCursor)) { + pSoftwareCursor->Width = 0; + pSoftwareCursor->Height = 0; + pSoftwareCursor->X = 0; + pSoftwareCursor->Y = 0; + pSoftwareCursor->ResetCursor = false; + } } return m_implicitSwapchain->Present(