diff --git a/DDrawCompat/Common/VtableHookVisitor.h b/DDrawCompat/Common/VtableHookVisitor.h index 3695100..14a776c 100644 --- a/DDrawCompat/Common/VtableHookVisitor.h +++ b/DDrawCompat/Common/VtableHookVisitor.h @@ -6,7 +6,9 @@ #include "DDraw/ScopedThreadLock.h" struct _D3DDDI_ADAPTERCALLBACKS; +struct _D3DDDI_ADAPTERFUNCS; struct _D3DDDI_DEVICEALLBACKS; +struct _D3DDDI_DEVICEFUNCS; template class ScopedVtableFuncLock : public DDraw::ScopedThreadLock {}; @@ -14,9 +16,15 @@ class ScopedVtableFuncLock : public DDraw::ScopedThreadLock {}; template <> class ScopedVtableFuncLock<_D3DDDI_ADAPTERCALLBACKS> : public D3dDdi::ScopedCriticalSection {}; +template <> +class ScopedVtableFuncLock<_D3DDDI_ADAPTERFUNCS> : public D3dDdi::ScopedCriticalSection {}; + template <> class ScopedVtableFuncLock<_D3DDDI_DEVICEALLBACKS> : public D3dDdi::ScopedCriticalSection {}; +template <> +class ScopedVtableFuncLock<_D3DDDI_DEVICEFUNCS> : public D3dDdi::ScopedCriticalSection {}; + template class VtableHookVisitor { diff --git a/DDrawCompat/D3dDdi/Device.cpp b/DDrawCompat/D3dDdi/Device.cpp index f0ed921..f9ed8cd 100644 --- a/DDrawCompat/D3dDdi/Device.cpp +++ b/DDrawCompat/D3dDdi/Device.cpp @@ -6,34 +6,13 @@ #include "D3dDdi/Device.h" #include "D3dDdi/DeviceFuncs.h" #include "D3dDdi/Resource.h" -#include "Gdi/AccessGuard.h" namespace { HANDLE g_gdiResourceHandle = nullptr; + D3dDdi::Resource* g_gdiResource = nullptr; bool g_isReadOnlyGdiLockEnabled = false; - class RenderGuard : public Gdi::DDrawAccessGuard - { - public: - RenderGuard(D3dDdi::Device& device, Gdi::Access access) - : Gdi::DDrawAccessGuard(access) - , m_device(device) - { - device.prepareForRendering(); - } - - RenderGuard(D3dDdi::Device& device, Gdi::Access access, HANDLE resource, UINT subResourceIndex = UINT_MAX) - : Gdi::DDrawAccessGuard(access, g_gdiResourceHandle == resource) - , m_device(device) - { - device.prepareForRendering(resource, subResourceIndex, Gdi::ACCESS_READ == access); - } - - private: - D3dDdi::Device& m_device; - }; - template void erase_if(Container& container, Predicate pred) { @@ -69,14 +48,13 @@ namespace D3dDdi { return it->second.blt(data); } - RenderGuard srcRenderGuard(*this, Gdi::ACCESS_READ, data.hSrcResource, data.SrcSubResourceIndex); - RenderGuard dstRenderGuard(*this, Gdi::ACCESS_WRITE, data.hDstResource, data.DstSubResourceIndex); + prepareForRendering(data.hSrcResource, data.SrcSubResourceIndex, true); return m_origVtable.pfnBlt(m_device, &data); } HRESULT Device::clear(const D3DDDIARG_CLEAR& data, UINT numRect, const RECT* rect) { - RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE); + prepareForRendering(); return m_origVtable.pfnClear(m_device, &data, numRect, rect); } @@ -87,7 +65,6 @@ namespace D3dDdi { return it->second.colorFill(data); } - RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE, data.hResource, data.SubResourceIndex); return m_origVtable.pfnColorFill(m_device, &data); } @@ -118,6 +95,17 @@ namespace D3dDdi HRESULT Device::destroyResource(HANDLE resource) { + if (g_gdiResource && resource == *g_gdiResource) + { + D3DDDIARG_LOCK lock = {}; + lock.hResource = *g_gdiResource; + g_gdiResource->lock(lock); + + D3DDDIARG_UNLOCK unlock = {}; + unlock.hResource = *g_gdiResource; + g_gdiResource->unlock(unlock); + } + if (resource == m_sharedPrimary) { D3DKMTReleaseProcessVidPnSourceOwners(GetCurrentProcess()); @@ -145,6 +133,7 @@ namespace D3dDdi if (resource == g_gdiResourceHandle) { g_gdiResourceHandle = nullptr; + g_gdiResource = nullptr; } } @@ -153,55 +142,50 @@ namespace D3dDdi HRESULT Device::drawIndexedPrimitive(const D3DDDIARG_DRAWINDEXEDPRIMITIVE& data) { - RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE); + prepareForRendering(); return m_origVtable.pfnDrawIndexedPrimitive(m_device, &data); } HRESULT Device::drawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2& data, UINT indicesSize, const void* indexBuffer, const UINT* flagBuffer) { - RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE); + prepareForRendering(); return m_origVtable.pfnDrawIndexedPrimitive2(m_device, &data, indicesSize, indexBuffer, flagBuffer); } HRESULT Device::drawPrimitive(const D3DDDIARG_DRAWPRIMITIVE& data, const UINT* flagBuffer) { - RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE); + prepareForRendering(); return m_origVtable.pfnDrawPrimitive(m_device, &data, flagBuffer); } HRESULT Device::drawPrimitive2(const D3DDDIARG_DRAWPRIMITIVE2& data) { - RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE); + prepareForRendering(); return m_origVtable.pfnDrawPrimitive2(m_device, &data); } HRESULT Device::drawRectPatch(const D3DDDIARG_DRAWRECTPATCH& data, const D3DDDIRECTPATCH_INFO* info, const FLOAT* patch) { - RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE); + prepareForRendering(); return m_origVtable.pfnDrawRectPatch(m_device, &data, info, patch); } HRESULT Device::drawTriPatch(const D3DDDIARG_DRAWTRIPATCH& data, const D3DDDITRIPATCH_INFO* info, const FLOAT* patch) { - RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE); + prepareForRendering(); return m_origVtable.pfnDrawTriPatch(m_device, &data, info, patch); } HRESULT Device::lock(D3DDDIARG_LOCK& data) { - Gdi::DDrawAccessGuard accessGuard( - (data.Flags.ReadOnly || g_isReadOnlyGdiLockEnabled) ? Gdi::ACCESS_READ : Gdi::ACCESS_WRITE, - data.hResource == g_gdiResourceHandle); - auto it = m_resources.find(data.hResource); if (it != m_resources.end()) { return it->second.lock(data); } - return m_origVtable.pfnLock(m_device, &data); } @@ -217,53 +201,40 @@ namespace D3dDdi HRESULT Device::present(const D3DDDIARG_PRESENT& data) { - RenderGuard renderGuard(*this, Gdi::ACCESS_READ, data.hSrcResource, data.SrcSubResourceIndex); + prepareForRendering(data.hSrcResource, data.SrcSubResourceIndex, true); return m_origVtable.pfnPresent(m_device, &data); } HRESULT Device::present1(D3DDDIARG_PRESENT1& data) { - bool isGdiResourceInvolved = false; - for (UINT i = 0; i < data.SrcResources && !isGdiResourceInvolved; ++i) - { - isGdiResourceInvolved = data.phSrcResources[i].hResource == g_gdiResourceHandle; - } - - Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_READ, isGdiResourceInvolved); - for (UINT i = 0; i < data.SrcResources; ++i) { - const bool isReadOnly = true; - prepareForRendering(data.phSrcResources[i].hResource, data.phSrcResources[i].SubResourceIndex, isReadOnly); + prepareForRendering(data.phSrcResources[i].hResource, data.phSrcResources[i].SubResourceIndex, true); } - return m_origVtable.pfnPresent1(m_device, &data); } HRESULT Device::texBlt(const D3DDDIARG_TEXBLT& data) { - RenderGuard dstRenderGuard(*this, Gdi::ACCESS_WRITE, data.hDstResource); - RenderGuard srcRenderGuard(*this, Gdi::ACCESS_READ, data.hSrcResource); + prepareForRendering(data.hDstResource, UINT_MAX, false); + prepareForRendering(data.hSrcResource, UINT_MAX, true); return m_origVtable.pfnTexBlt(m_device, &data); } HRESULT Device::texBlt1(const D3DDDIARG_TEXBLT1& data) { - RenderGuard dstRenderGuard(*this, Gdi::ACCESS_WRITE, data.hDstResource); - RenderGuard srcRenderGuard(*this, Gdi::ACCESS_READ, data.hSrcResource); + prepareForRendering(data.hDstResource, UINT_MAX, false); + prepareForRendering(data.hSrcResource, UINT_MAX, true); return m_origVtable.pfnTexBlt1(m_device, &data); } HRESULT Device::unlock(const D3DDDIARG_UNLOCK& data) { - Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_READ, data.hResource == g_gdiResourceHandle); - auto it = m_resources.find(data.hResource); if (it != m_resources.end()) { return it->second.unlock(data); } - return m_origVtable.pfnUnlock(m_device, &data); } @@ -289,6 +260,11 @@ namespace D3dDdi m_dirtyTextures.emplace(std::make_pair(resource, subResourceIndex), resource); } + Resource* Device::getGdiResource() + { + return g_gdiResource; + } + void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly) { auto it = m_resources.find(resource); @@ -366,6 +342,11 @@ namespace D3dDdi void Device::setGdiResourceHandle(HANDLE resource) { g_gdiResourceHandle = resource; + g_gdiResource = getResource(resource); + if (g_gdiResource) + { + g_gdiResource->resync(); + } } void Device::setReadOnlyGdiLock(bool enable) diff --git a/DDrawCompat/D3dDdi/Device.h b/DDrawCompat/D3dDdi/Device.h index fd65d12..abfb21f 100644 --- a/DDrawCompat/D3dDdi/Device.h +++ b/DDrawCompat/D3dDdi/Device.h @@ -56,6 +56,7 @@ namespace D3dDdi static Device& get(HANDLE device); static void remove(HANDLE device); + static Resource* getGdiResource(); static Resource* getResource(HANDLE resource); static void setGdiResourceHandle(HANDLE resource); static void setReadOnlyGdiLock(bool enable); diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 4f29b73..a486432 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -467,6 +467,18 @@ namespace D3dDdi return m_device.getOrigVtable().pfnBlt(m_device, &data); } + void Resource::resync() + { + if (!m_lockData.empty() && m_lockData[0].isSysMemUpToDate) + { + copySubResource(*this, *m_lockResource, 0); + if (!m_lockData[0].isVidMemUpToDate) + { + setVidMemUpToDate(0, true); + } + } + } + void Resource::setLockResource(Resource* lockResource) { if (!m_lockResource == !lockResource) diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index 2740e3a..129dca3 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -30,6 +30,7 @@ namespace D3dDdi void destroy(); HRESULT lock(D3DDDIARG_LOCK& data); void prepareForRendering(UINT subResourceIndex, bool isReadOnly); + void resync(); void setLockResource(Resource* lockResource); void setRootSurface(DDraw::Surface* rootSurface); HRESULT unlock(const D3DDDIARG_UNLOCK& data); diff --git a/DDrawCompat/DDraw/ActivateAppHandler.cpp b/DDrawCompat/DDraw/ActivateAppHandler.cpp index 5e53a7c..7e23b3b 100644 --- a/DDrawCompat/DDraw/ActivateAppHandler.cpp +++ b/DDrawCompat/DDraw/ActivateAppHandler.cpp @@ -1,5 +1,3 @@ -#include - #include #include "Common/Hook.h" @@ -14,8 +12,6 @@ namespace { Win32::FontSmoothing::SystemSettings g_fontSmoothingSettings = {}; WNDPROC g_origDdWndProc = nullptr; - std::atomic g_activateAppThreadId = 0; - HWND g_delayedFocusWnd = nullptr; void activateApp() { @@ -37,7 +33,6 @@ namespace { case WM_ACTIVATEAPP: { - DDraw::RealPrimarySurface::disableUpdates(); isDisplayChangeNotificationEnabled = false; if (TRUE == wParam) { @@ -48,17 +43,9 @@ namespace deactivateApp(); } - g_activateAppThreadId = GetCurrentThreadId(); - g_delayedFocusWnd = nullptr; LRESULT result = g_origDdWndProc(hwnd, uMsg, wParam, lParam); - g_activateAppThreadId = 0; - if (g_delayedFocusWnd) - { - CALL_ORIG_FUNC(SetFocus)(g_delayedFocusWnd); - } isDisplayChangeNotificationEnabled = true; - DDraw::RealPrimarySurface::enableUpdates(); return LOG_RESULT(result); } @@ -75,39 +62,12 @@ namespace return LOG_RESULT(g_origDdWndProc(hwnd, uMsg, wParam, lParam)); } - - HWND WINAPI setFocus(HWND hWnd) - { - if (GetCurrentThreadId() == g_activateAppThreadId && IsWindow(hWnd)) - { - g_delayedFocusWnd = hWnd; - return GetFocus(); - } - return CALL_ORIG_FUNC(SetFocus)(hWnd); - } - - BOOL WINAPI showWindow(HWND hWnd, int nCmdShow) - { - if (GetCurrentThreadId() == g_activateAppThreadId && IsWindow(hWnd)) - { - BOOL result = IsWindowVisible(hWnd); - ShowWindowAsync(hWnd, nCmdShow); - return result; - } - return CALL_ORIG_FUNC(ShowWindow)(hWnd, nCmdShow); - } } namespace DDraw { namespace ActivateAppHandler { - void installHooks() - { - HOOK_FUNCTION(user32, SetFocus, setFocus); - HOOK_FUNCTION(user32, ShowWindow, showWindow); - } - void setCooperativeLevel(HWND hwnd, DWORD flags) { static bool isDdWndProcHooked = false; diff --git a/DDrawCompat/DDraw/ActivateAppHandler.h b/DDrawCompat/DDraw/ActivateAppHandler.h index 96aa995..df0ce9f 100644 --- a/DDrawCompat/DDraw/ActivateAppHandler.h +++ b/DDrawCompat/DDraw/ActivateAppHandler.h @@ -8,7 +8,6 @@ namespace DDraw { namespace ActivateAppHandler { - void installHooks(); void setCooperativeLevel(HWND hwnd, DWORD flags); } } diff --git a/DDrawCompat/DDraw/Hooks.cpp b/DDrawCompat/DDraw/Hooks.cpp index 827a527..f17c5d0 100644 --- a/DDrawCompat/DDraw/Hooks.cpp +++ b/DDrawCompat/DDraw/Hooks.cpp @@ -1,6 +1,5 @@ #include "Common/CompatRef.h" #include "Common/Log.h" -#include "DDraw/ActivateAppHandler.h" #include "DDraw/DirectDraw.h" #include "DDraw/DirectDrawClipper.h" #include "DDraw/DirectDrawGammaControl.h" @@ -95,7 +94,6 @@ namespace DDraw void installHooks(CompatPtr dd7) { RealPrimarySurface::init(); - ActivateAppHandler::installHooks(); Win32::Registry::unsetValue( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\DirectDraw", "EmulationOnly"); diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index d4a664c..54ba4ff 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -34,7 +34,7 @@ namespace bool g_stopUpdateThread = false; HANDLE g_updateThread = nullptr; - unsigned int g_disableUpdateCount = 0; + bool g_isGdiUpdatePending = false; bool g_isFlipPending = false; bool g_isPresentPending = false; bool g_isUpdatePending = false; @@ -91,7 +91,7 @@ namespace } } - Gdi::GdiAccessGuard gdiAccessGuard(Gdi::ACCESS_READ, !primaryRegion); + Gdi::AccessGuard accessGuard(Gdi::ACCESS_READ, !primaryRegion); HWND presentationWindow = windowPair.second->getPresentationWindow(); HDC dc = GetWindowDC(presentationWindow); RECT rect = windowPair.second->getWindowRect(); @@ -369,7 +369,6 @@ namespace Gdi::Region primaryRegion(D3dDdi::KernelModeThunks::getMonitorRect()); bltToWindowViaGdi(&primaryRegion); - Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_READ, DDraw::PrimarySurface::isGdiSurface(src.get())); if (Win32::DisplayMode::getBpp() <= 8) { HDC paletteConverterDc = nullptr; @@ -437,12 +436,19 @@ namespace void updateNowIfNotBusy() { + if (g_isGdiUpdatePending) + { + g_qpcLastUpdate = Time::queryPerformanceCounter(); + g_isUpdatePending = true; + g_isGdiUpdatePending = false; + } + auto primary(DDraw::PrimarySurface::getPrimary()); RECT emptyRect = {}; HRESULT result = primary ? primary->BltFast(primary, 0, 0, primary, &emptyRect, DDBLTFAST_WAIT) : DD_OK; g_waitingForPrimaryUnlock = DDERR_SURFACEBUSY == result || DDERR_LOCKEDSURFACES == result; - if (!g_waitingForPrimaryUnlock && DDERR_SURFACELOST != result) + if (!g_waitingForPrimaryUnlock) { const auto msSinceLastUpdate = Time::qpcToMs(Time::queryPerformanceCounter() - g_qpcLastUpdate); updateNow(primary, msSinceLastUpdate > Config::delayedFlipModeTimeout ? 0 : 1); @@ -472,7 +478,7 @@ namespace waitForVBlank = Time::qpcToMs(Time::queryPerformanceCounter() - D3dDdi::KernelModeThunks::getQpcLastVerticalBlank()) >= msPresentDelayAfterVBlank; - if (waitForVBlank && g_isUpdatePending && 0 == g_disableUpdateCount && !isPresentPending()) + if (waitForVBlank && (g_isUpdatePending || g_isGdiUpdatePending) && !isPresentPending()) { updateNowIfNotBusy(); } @@ -532,18 +538,6 @@ namespace DDraw template HRESULT RealPrimarySurface::create(CompatRef); template HRESULT RealPrimarySurface::create(CompatRef); - void RealPrimarySurface::disableUpdates() - { - DDraw::ScopedThreadLock lock; - --g_disableUpdateCount; - } - - void RealPrimarySurface::enableUpdates() - { - DDraw::ScopedThreadLock lock; - ++g_disableUpdateCount; - } - HRESULT RealPrimarySurface::flip(CompatPtr surfaceTargetOverride, DWORD flags) { DDraw::ScopedThreadLock lock; @@ -587,6 +581,11 @@ namespace DDraw return DD_OK; } + void RealPrimarySurface::gdiUpdate() + { + g_isGdiUpdatePending = true; + } + HRESULT RealPrimarySurface::getGammaRamp(DDGAMMARAMP* rampData) { DDraw::ScopedThreadLock lock; diff --git a/DDrawCompat/DDraw/RealPrimarySurface.h b/DDrawCompat/DDraw/RealPrimarySurface.h index 518afca..2b75767 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.h +++ b/DDrawCompat/DDraw/RealPrimarySurface.h @@ -15,9 +15,8 @@ namespace DDraw template static HRESULT create(CompatRef dd); - static void disableUpdates(); - static void enableUpdates(); static HRESULT flip(CompatPtr surfaceTargetOverride, DWORD flags); + static void gdiUpdate(); static HRESULT getGammaRamp(DDGAMMARAMP* rampData); static CompatWeakPtr getSurface(); static void init(); diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp index 0ebe0a8..3bef74d 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp @@ -8,11 +8,14 @@ #include "DDraw/RealPrimarySurface.h" #include "DDraw/Surfaces/PrimarySurface.h" #include "DDraw/Surfaces/PrimarySurfaceImpl.h" +#include "Gdi/VirtualScreen.h" namespace { CompatWeakPtr g_primarySurface; + std::vector> g_lockBackBuffers; HANDLE g_gdiResourceHandle = nullptr; + HANDLE g_frontResource = nullptr; DWORD g_origCaps = 0; } @@ -23,11 +26,18 @@ namespace DDraw LOG_FUNC("PrimarySurface::~PrimarySurface"); g_gdiResourceHandle = nullptr; + g_frontResource = nullptr; g_primarySurface = nullptr; g_origCaps = 0; s_palette = nullptr; ZeroMemory(&s_paletteEntries, sizeof(s_paletteEntries)); + for (auto& lockBuffer : g_lockBackBuffers) + { + lockBuffer.release(); + } + g_lockBackBuffers.clear(); + DDraw::RealPrimarySurface::release(); } @@ -50,7 +60,9 @@ namespace DDraw desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM; desc.ddpfPixelFormat = dm.ddpfPixelFormat; - result = Surface::create(dd, desc, surface, std::make_unique()); + auto privateData(std::make_unique()); + auto data = privateData.get(); + result = Surface::create(dd, desc, surface, std::move(privateData)); if (FAILED(result)) { Compat::Log() << "ERROR: Failed to create the compat primary surface: " << Compat::hex(result); @@ -58,11 +70,32 @@ namespace DDraw return result; } - g_primarySurface = CompatPtr::from(surface); g_origCaps = origCaps; - onRestore(); + data->m_lockSurface.release(); + data->m_attachedLockSurfaces.clear(); + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; + desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + CompatPtr lockSurface; + dd->CreateSurface(&dd, &desc, &lockSurface.getRef(), nullptr); + data->m_lockSurface = lockSurface; + + if (g_origCaps & DDSCAPS_FLIP) + { + for (std::size_t i = 0; i < desc.dwBackBufferCount; ++i) + { + CompatPtr lockBuffer; + dd->CreateSurface(&dd, &desc, &lockBuffer.getRef(), nullptr); + if (lockBuffer) + { + g_lockBackBuffers.push_back(CompatPtr::from(lockBuffer.get()).detach()); + data->m_attachedLockSurfaces.push_back(g_lockBackBuffers.back()); + } + } + } + + data->restore(); return DD_OK; } @@ -152,6 +185,11 @@ namespace DDraw return g_primarySurface; } + HANDLE PrimarySurface::getFrontResource() + { + return g_frontResource; + } + DWORD PrimarySurface::getOrigCaps() { return g_origCaps; @@ -169,10 +207,28 @@ namespace DDraw template bool PrimarySurface::isGdiSurface(IDirectDrawSurface4*); template bool PrimarySurface::isGdiSurface(IDirectDrawSurface7*); - void PrimarySurface::onRestore() + void PrimarySurface::restore() { + LOG_FUNC("PrimarySurface::restore"); + + clearResources(); + + Gdi::VirtualScreen::update(); + auto desc = Gdi::VirtualScreen::getSurfaceDesc(D3dDdi::KernelModeThunks::getMonitorRect()); + desc.dwFlags &= ~DDSD_CAPS; + m_lockSurface->SetSurfaceDesc(m_lockSurface, &desc, 0); + + g_primarySurface = m_surface; g_gdiResourceHandle = getRuntimeResourceHandle(*g_primarySurface); - D3dDdi::Device::setGdiResourceHandle(*reinterpret_cast(g_gdiResourceHandle)); + updateFrontResource(); + D3dDdi::Device::setGdiResourceHandle(g_frontResource); + + Surface::restore(); + } + + void PrimarySurface::updateFrontResource() + { + g_frontResource = getDriverResourceHandle(*g_primarySurface); } void PrimarySurface::updatePalette() diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurface.h b/DDrawCompat/DDraw/Surfaces/PrimarySurface.h index eef857c..f33a948 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurface.h +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurface.h @@ -21,13 +21,17 @@ namespace DDraw static CompatPtr getBackBuffer(); static CompatPtr getLastSurface(); static CompatWeakPtr getPrimary(); + static HANDLE getFrontResource(); static DWORD getOrigCaps(); - static void onRestore(); static void updatePalette(); template static bool isGdiSurface(TSurface* surface); + static void updateFrontResource(); + + virtual void restore(); + static CompatWeakPtr s_palette; static PALETTEENTRY s_paletteEntries[256]; diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp index 9748728..597ec0c 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurfaceImpl.cpp @@ -134,6 +134,7 @@ namespace DDraw return result; } + PrimarySurface::updateFrontResource(); return RealPrimarySurface::flip(surfaceTargetOverride, dwFlags); } @@ -208,11 +209,7 @@ namespace DDraw result = RealPrimarySurface::restore(); if (SUCCEEDED(result)) { - result = SurfaceImpl::Restore(This); - if (SUCCEEDED(result)) - { - PrimarySurface::onRestore(); - } + return SurfaceImpl::Restore(This); } } return result; diff --git a/DDrawCompat/DDraw/Surfaces/Surface.cpp b/DDrawCompat/DDraw/Surfaces/Surface.cpp index 33be56e..b964f43 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.cpp +++ b/DDrawCompat/DDraw/Surfaces/Surface.cpp @@ -213,8 +213,6 @@ namespace DDraw return LOG_RESULT(nullptr); } - desc.dwFlags |= DDSD_PIXELFORMAT; - desc.ddpfPixelFormat = desc.ddpfPixelFormat; desc.ddsCaps.dwCaps &= ~(DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM); desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; diff --git a/DDrawCompat/DDraw/Surfaces/Surface.h b/DDrawCompat/DDraw/Surfaces/Surface.h index 3df117d..8885fd3 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.h +++ b/DDrawCompat/DDraw/Surfaces/Surface.h @@ -34,7 +34,7 @@ namespace DDraw SurfaceImpl* getImpl() const; void clearResources(); - void restore(); + virtual void restore(); protected: static void attach(CompatRef dds, std::unique_ptr privateData); @@ -48,6 +48,11 @@ namespace DDraw std::unique_ptr> m_impl4; std::unique_ptr> m_impl7; + CompatWeakPtr m_surface; + std::vector m_attachedSurfaces; + CompatPtr m_lockSurface; + std::vector> m_attachedLockSurfaces; + private: template friend class SurfaceImpl; @@ -61,9 +66,5 @@ namespace DDraw DWORD m_refCount; Surface* m_rootSurface; - CompatWeakPtr m_surface; - std::vector m_attachedSurfaces; - CompatPtr m_lockSurface; - std::vector> m_attachedLockSurfaces; }; } diff --git a/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp b/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp index 4b34f9f..1d24750 100644 --- a/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp +++ b/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp @@ -5,7 +5,6 @@ #include "DDraw/Surfaces/PrimarySurface.h" #include "DDraw/Surfaces/Surface.h" #include "DDraw/Surfaces/SurfaceImpl.h" -#include "Gdi/AccessGuard.h" namespace { @@ -36,9 +35,6 @@ namespace DDraw { return DDERR_WASSTILLDRAWING; } - - Gdi::DDrawAccessGuard dstAccessGuard(Gdi::ACCESS_WRITE, PrimarySurface::isGdiSurface(This)); - Gdi::DDrawAccessGuard srcAccessGuard(Gdi::ACCESS_READ, PrimarySurface::isGdiSurface(lpDDSrcSurface)); return s_origVtable.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); } @@ -46,8 +42,6 @@ namespace DDraw HRESULT SurfaceImpl::BltFast( TSurface* This, DWORD dwX, DWORD dwY, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) { - Gdi::DDrawAccessGuard dstAccessGuard(Gdi::ACCESS_WRITE, PrimarySurface::isGdiSurface(This)); - Gdi::DDrawAccessGuard srcAccessGuard(Gdi::ACCESS_READ, PrimarySurface::isGdiSurface(lpDDSrcSurface)); return s_origVtable.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans); } @@ -81,18 +75,11 @@ namespace DDraw template HRESULT SurfaceImpl::GetDC(TSurface* This, HDC* lphDC) { - HRESULT result = DD_OK; - - { - Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_WRITE); - result = s_origVtable.GetDC(This, lphDC); - } - + HRESULT result = s_origVtable.GetDC(This, lphDC); if (SUCCEEDED(result)) { RealPrimarySurface::waitForFlip(m_data); } - return result; } @@ -143,8 +130,6 @@ namespace DDraw return DDERR_WASSTILLDRAWING; } - Gdi::DDrawAccessGuard accessGuard((dwFlags & DDLOCK_READONLY) ? Gdi::ACCESS_READ : Gdi::ACCESS_WRITE, - PrimarySurface::isGdiSurface(This)); HRESULT result = s_origVtable.Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent); if (DDERR_SURFACELOST == result) { @@ -164,7 +149,6 @@ namespace DDraw template HRESULT SurfaceImpl::ReleaseDC(TSurface* This, HDC hDC) { - Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_READ, PrimarySurface::isGdiSurface(This)); return s_origVtable.ReleaseDC(This, hDC); } @@ -188,7 +172,6 @@ namespace DDraw template HRESULT SurfaceImpl::Unlock(TSurface* This, TUnlockParam lpRect) { - Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_READ, PrimarySurface::isGdiSurface(This)); return s_origVtable.Unlock(This, lpRect); } diff --git a/DDrawCompat/Gdi/AccessGuard.cpp b/DDrawCompat/Gdi/AccessGuard.cpp index 93ef5cc..4063d57 100644 --- a/DDrawCompat/Gdi/AccessGuard.cpp +++ b/DDrawCompat/Gdi/AccessGuard.cpp @@ -1,151 +1,43 @@ -#define WIN32_LEAN_AND_MEAN - -#include - -#include "D3dDdi/KernelModeThunks.h" +#include "D3dDdi/Device.h" +#include "D3dDdi/Resource.h" #include "DDraw/RealPrimarySurface.h" -#include "DDraw/ScopedThreadLock.h" #include "DDraw/Surfaces/PrimarySurface.h" #include "Gdi/AccessGuard.h" -#include "Gdi/VirtualScreen.h" - -namespace -{ - struct Accessor - { - DWORD readAccessDepth; - DWORD writeAccessDepth; - bool isSynced; - - Accessor(bool isSynced) : readAccessDepth(0), writeAccessDepth(0), isSynced(isSynced) {} - }; - - Accessor g_ddrawAccessor(false); - Accessor g_gdiAccessor(true); - bool g_isSyncing = false; - - bool synchronize(Gdi::User user); - - void beginAccess(Gdi::User user, Gdi::Access access) - { - LOG_FUNC("beginAccess", user, access); - - Accessor& accessor = Gdi::USER_DDRAW == user ? g_ddrawAccessor : g_gdiAccessor; - DWORD& accessDepth = Gdi::ACCESS_READ == access ? accessor.readAccessDepth : accessor.writeAccessDepth; - ++accessDepth; - - accessor.isSynced = accessor.isSynced || synchronize(user); - if (accessor.isSynced && Gdi::ACCESS_WRITE == access) - { - Accessor& otherAccessor = Gdi::USER_DDRAW == user ? g_gdiAccessor : g_ddrawAccessor; - otherAccessor.isSynced = false; - } - - LOG_RESULT(accessor.isSynced); - } - - void endAccess(Gdi::User user, Gdi::Access access) - { - LOG_FUNC("endAccess", user, access); - - Accessor& accessor = Gdi::USER_DDRAW == user ? g_ddrawAccessor : g_gdiAccessor; - DWORD& accessDepth = Gdi::ACCESS_READ == access ? accessor.readAccessDepth : accessor.writeAccessDepth; - --accessDepth; - - if (Gdi::USER_DDRAW == user && - 0 == g_ddrawAccessor.readAccessDepth && 0 == g_ddrawAccessor.writeAccessDepth && - (0 != g_gdiAccessor.readAccessDepth || 0 != g_gdiAccessor.writeAccessDepth)) - { - g_gdiAccessor.isSynced = g_gdiAccessor.isSynced || synchronize(Gdi::USER_GDI); - if (g_gdiAccessor.isSynced && 0 != g_gdiAccessor.writeAccessDepth) - { - g_ddrawAccessor.isSynced = false; - } - } - - if (0 == accessDepth && Gdi::ACCESS_WRITE == access && Gdi::USER_GDI == user && - 0 == g_ddrawAccessor.writeAccessDepth) - { - auto primary(DDraw::PrimarySurface::getPrimary()); - if (!primary || DDraw::PrimarySurface::isGdiSurface(primary.get())) - { - DDraw::RealPrimarySurface::update(); - } - } - } - - bool synchronize(Gdi::User user) - { - auto ddrawSurface(DDraw::PrimarySurface::getGdiSurface()); - if (!ddrawSurface) - { - return false; - } - - auto gdiSurface(Gdi::VirtualScreen::createSurface(D3dDdi::KernelModeThunks::getMonitorRect())); - if (!gdiSurface) - { - return false; - } - - bool result = true; - g_isSyncing = true; - if (Gdi::USER_DDRAW == user) - { - CompatPtr clipper; - ddrawSurface->GetClipper(ddrawSurface, &clipper.getRef()); - ddrawSurface->SetClipper(ddrawSurface, nullptr); - result = SUCCEEDED(ddrawSurface.get()->lpVtbl->Blt( - ddrawSurface, nullptr, gdiSurface, nullptr, DDBLT_WAIT, nullptr)); - ddrawSurface->SetClipper(ddrawSurface, clipper); - } - else - { - result = SUCCEEDED(gdiSurface.get()->lpVtbl->BltFast( - gdiSurface, 0, 0, ddrawSurface, nullptr, DDBLTFAST_WAIT)); - } - g_isSyncing = false; - - return result; - } -} namespace Gdi { - AccessGuard::AccessGuard(User user, Access access, bool condition) - : m_user(user) - , m_access(access) + AccessGuard::AccessGuard(Access access, bool condition) + : m_access(access) , m_condition(condition) { if (m_condition) { - DDraw::ScopedThreadLock lock; - if (g_isSyncing) + D3dDdi::ScopedCriticalSection lock; + auto gdiResource = D3dDdi::Device::getGdiResource(); + if (gdiResource) { - m_condition = false; - return; - } + D3DDDIARG_LOCK lockData = {}; + lockData.hResource = gdiResource; + lockData.Flags.ReadOnly = ACCESS_READ == access; + gdiResource->lock(lockData); - beginAccess(user, access); + D3DDDIARG_UNLOCK unlockData = {}; + unlockData.hResource = gdiResource; + gdiResource->unlock(unlockData); + } } } AccessGuard::~AccessGuard() { - if (m_condition) + if (m_condition && ACCESS_WRITE == m_access) { - DDraw::ScopedThreadLock lock; - endAccess(m_user, m_access); + D3dDdi::ScopedCriticalSection lock; + auto gdiResource = D3dDdi::Device::getGdiResource(); + if (!gdiResource || DDraw::PrimarySurface::getFrontResource() == *gdiResource) + { + DDraw::RealPrimarySurface::gdiUpdate(); + } } } - - DDrawAccessGuard::DDrawAccessGuard(Access access, bool condition) - : AccessGuard(USER_DDRAW, access, condition) - { - } - - GdiAccessGuard::GdiAccessGuard(Access access, bool condition) - : AccessGuard(USER_GDI, access, condition) - { - } } diff --git a/DDrawCompat/Gdi/AccessGuard.h b/DDrawCompat/Gdi/AccessGuard.h index ad46533..b1296a3 100644 --- a/DDrawCompat/Gdi/AccessGuard.h +++ b/DDrawCompat/Gdi/AccessGuard.h @@ -1,5 +1,10 @@ #pragma once +namespace D3dDdi +{ + class Resource; +} + namespace Gdi { enum Access @@ -8,33 +13,14 @@ namespace Gdi ACCESS_WRITE }; - enum User - { - USER_DDRAW, - USER_GDI - }; - class AccessGuard { - protected: - AccessGuard(User user, Access access, bool condition = true); + public: + AccessGuard(Access access, bool condition = true); ~AccessGuard(); private: - User m_user; Access m_access; bool m_condition; }; - - class DDrawAccessGuard : public AccessGuard - { - public: - DDrawAccessGuard(Access access, bool condition = true); - }; - - class GdiAccessGuard : public AccessGuard - { - public: - GdiAccessGuard(Access access, bool condition = true); - }; } diff --git a/DDrawCompat/Gdi/Caret.cpp b/DDrawCompat/Gdi/Caret.cpp index a8ec942..2bb9e58 100644 --- a/DDrawCompat/Gdi/Caret.cpp +++ b/DDrawCompat/Gdi/Caret.cpp @@ -4,7 +4,7 @@ #include "Common/Hook.h" #include "Common/Time.h" -#include "DDraw/ScopedThreadLock.h" +#include "D3dDdi/ScopedCriticalSection.h" #include "Gdi/Caret.h" extern "C" IMAGE_DOS_HEADER __ImageBase; @@ -34,7 +34,6 @@ namespace { if (OBJID_CARET == idObject) { - DDraw::ScopedThreadLock lock; updateCaret(GetWindowThreadProcessId(hwnd, nullptr)); } } @@ -64,7 +63,7 @@ namespace void updateCaret(DWORD threadId) { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; if (g_caret.isDrawn) { drawCaret(); @@ -87,7 +86,7 @@ namespace Gdi { void blink() { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; if (!g_caret.isVisible) { return; diff --git a/DDrawCompat/Gdi/Dc.cpp b/DDrawCompat/Gdi/Dc.cpp index 22b82a8..8df8a92 100644 --- a/DDrawCompat/Gdi/Dc.cpp +++ b/DDrawCompat/Gdi/Dc.cpp @@ -5,7 +5,7 @@ #include "Common/Hook.h" #include "Common/Log.h" #include "Common/ScopedCriticalSection.h" -#include "DDraw/ScopedThreadLock.h" +#include "D3dDdi/ScopedCriticalSection.h" #include "Gdi/Dc.h" #include "Gdi/DcCache.h" #include "Gdi/Gdi.h" @@ -185,7 +185,7 @@ namespace Gdi return nullptr; } - DDraw::ScopedThreadLock ddLock; + D3dDdi::ScopedCriticalSection driverLock; Compat::ScopedCriticalSection lock(g_cs); auto it = g_origDcToCompatDc.find(origDc); if (it != g_origDcToCompatDc.end()) diff --git a/DDrawCompat/Gdi/DcFunctions.cpp b/DDrawCompat/Gdi/DcFunctions.cpp index b0373b5..bed73bf 100644 --- a/DDrawCompat/Gdi/DcFunctions.cpp +++ b/DDrawCompat/Gdi/DcFunctions.cpp @@ -105,7 +105,7 @@ namespace if (hasDisplayDcArg(params...)) { const bool isReadOnlyAccess = !hasDisplayDcArg(getDestinationDc(params...)); - Gdi::GdiAccessGuard accessGuard(isReadOnlyAccess ? Gdi::ACCESS_READ : Gdi::ACCESS_WRITE); + Gdi::AccessGuard accessGuard(isReadOnlyAccess ? Gdi::ACCESS_READ : Gdi::ACCESS_WRITE); return LOG_RESULT(Compat::getOrigFuncPtr()(replaceDc(params)...)); } @@ -140,7 +140,7 @@ namespace } else { - Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE); + Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); return LOG_RESULT(CALL_ORIG_FUNC(ExtTextOutW)(replaceDc(hdc), x, y, options, lprect, lpString, c, lpDx)); } } diff --git a/DDrawCompat/Gdi/PaintHandlers.cpp b/DDrawCompat/Gdi/PaintHandlers.cpp index 0af46ea..3c4af05 100644 --- a/DDrawCompat/Gdi/PaintHandlers.cpp +++ b/DDrawCompat/Gdi/PaintHandlers.cpp @@ -2,6 +2,7 @@ #include "Common/Hook.h" #include "Common/Log.h" +#include "D3dDdi/ScopedCriticalSection.h" #include "DDraw/RealPrimarySurface.h" #include "Gdi/AccessGuard.h" #include "Gdi/Dc.h" @@ -254,7 +255,7 @@ namespace HDC compatDc = Gdi::Dc::getDc(dc); if (compatDc) { - Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE); + Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); result = CallWindowProc(origWndProc, hwnd, WM_ERASEBKGND, reinterpret_cast(compatDc), 0); Gdi::Dc::releaseDc(dc); return result; @@ -276,7 +277,7 @@ namespace if (compatDc) { - Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE); + Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); Gdi::TitleBar titleBar(hwnd, compatDc); titleBar.drawAll(); titleBar.excludeFromClipRegion(); @@ -301,14 +302,13 @@ namespace return CallWindowProc(origWndProc, hwnd, WM_PAINT, 0, 0); } - DDraw::ScopedThreadLock lock; PAINTSTRUCT paint = {}; HDC dc = BeginPaint(hwnd, &paint); HDC compatDc = Gdi::Dc::getDc(dc); if (compatDc) { - Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE); + Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); CallWindowProc(origWndProc, hwnd, WM_PRINTCLIENT, reinterpret_cast(compatDc), PRF_CLIENT); Gdi::Dc::releaseDc(dc); @@ -329,7 +329,7 @@ namespace HDC compatDc = Gdi::Dc::getDc(dc); if (compatDc) { - Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE); + Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); result = CallWindowProc(origWndProc, hwnd, msg, reinterpret_cast(compatDc), flags); Gdi::Dc::releaseDc(dc); } diff --git a/DDrawCompat/Gdi/ScrollFunctions.cpp b/DDrawCompat/Gdi/ScrollFunctions.cpp index e976be9..2aeb18d 100644 --- a/DDrawCompat/Gdi/ScrollFunctions.cpp +++ b/DDrawCompat/Gdi/ScrollFunctions.cpp @@ -1,6 +1,6 @@ #include "Common/Hook.h" #include "Common/Log.h" -#include "DDraw/ScopedThreadLock.h" +#include "D3dDdi/ScopedCriticalSection.h" #include "Gdi/Gdi.h" #include "Gdi/ScrollFunctions.h" #include "Gdi/Window.h" @@ -52,7 +52,7 @@ namespace Gdi void updateScrolledWindow(HWND hwnd) { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; auto window(Gdi::Window::get(hwnd)); UINT flags = RDW_ERASE | RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW; if (!window || window->getPresentationWindow() != hwnd) diff --git a/DDrawCompat/Gdi/VirtualScreen.cpp b/DDrawCompat/Gdi/VirtualScreen.cpp index f70c942..9a965f7 100644 --- a/DDrawCompat/Gdi/VirtualScreen.cpp +++ b/DDrawCompat/Gdi/VirtualScreen.cpp @@ -1,6 +1,8 @@ #include #include "Common/ScopedCriticalSection.h" +#include "D3dDdi/Device.h" +#include "D3dDdi/ScopedCriticalSection.h" #include "DDraw/DirectDraw.h" #include "DDraw/ScopedThreadLock.h" #include "DDraw/Surfaces/PrimarySurface.h" @@ -119,24 +121,12 @@ namespace Gdi DDraw::ScopedThreadLock ddLock; Compat::ScopedCriticalSection lock(g_cs); - if (rect.left < g_bounds.left || rect.top < g_bounds.top || - rect.right > g_bounds.right || rect.bottom > g_bounds.bottom) + auto desc = getSurfaceDesc(rect); + if (!desc.lpSurface) { return nullptr; } - DDSURFACEDESC2 desc = {}; - desc.dwSize = sizeof(desc); - desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH | DDSD_LPSURFACE; - desc.dwWidth = rect.right - rect.left; - desc.dwHeight = rect.bottom - rect.top; - desc.ddpfPixelFormat = DDraw::getRgbPixelFormat(g_bpp); - desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - desc.lPitch = g_pitch; - desc.lpSurface = static_cast(g_surfaceView) + - (rect.top - g_bounds.top) * g_pitch + - (rect.left - g_bounds.left) * g_bpp / 8; - auto primary(DDraw::PrimarySurface::getPrimary()); CompatPtr ddUnk; primary.get()->lpVtbl->GetDDInterface(primary, reinterpret_cast(&ddUnk.getRef())); @@ -172,6 +162,29 @@ namespace Gdi return g_region; } + DDSURFACEDESC2 getSurfaceDesc(const RECT& rect) + { + Compat::ScopedCriticalSection lock(g_cs); + if (rect.left < g_bounds.left || rect.top < g_bounds.top || + rect.right > g_bounds.right || rect.bottom > g_bounds.bottom) + { + return {}; + } + + DDSURFACEDESC2 desc = {}; + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH | DDSD_LPSURFACE; + desc.dwWidth = rect.right - rect.left; + desc.dwHeight = rect.bottom - rect.top; + desc.ddpfPixelFormat = DDraw::getRgbPixelFormat(g_bpp); + desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + desc.lPitch = g_pitch; + desc.lpSurface = static_cast(g_surfaceView) + + (rect.top - g_bounds.top) * g_pitch + + (rect.left - g_bounds.left) * g_bpp / 8; + return desc; + } + void init() { update(); @@ -192,6 +205,11 @@ namespace Gdi prevDisplaySettingsUniqueness = currentDisplaySettingsUniqueness; + { + D3dDdi::ScopedCriticalSection driverLock; + D3dDdi::Device::setGdiResourceHandle(nullptr); + } + g_region = Region(); EnumDisplayMonitors(nullptr, nullptr, addMonitorRectToRegion, reinterpret_cast(&g_region)); GetRgnBox(g_region, &g_bounds); diff --git a/DDrawCompat/Gdi/VirtualScreen.h b/DDrawCompat/Gdi/VirtualScreen.h index 3fa85cc..b0b4614 100644 --- a/DDrawCompat/Gdi/VirtualScreen.h +++ b/DDrawCompat/Gdi/VirtualScreen.h @@ -20,6 +20,7 @@ namespace Gdi RECT getBounds(); Region getRegion(); + DDSURFACEDESC2 getSurfaceDesc(const RECT& rect); void init(); bool update(); diff --git a/DDrawCompat/Gdi/WinProc.cpp b/DDrawCompat/Gdi/WinProc.cpp index f89db31..0b368e3 100644 --- a/DDrawCompat/Gdi/WinProc.cpp +++ b/DDrawCompat/Gdi/WinProc.cpp @@ -139,7 +139,7 @@ namespace HDC compatDc = Gdi::Dc::getDc(windowDc); if (compatDc) { - Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE); + Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); if (OBJID_TITLEBAR == idObject) { Gdi::TitleBar(hwnd, compatDc).drawButtons(); diff --git a/DDrawCompat/Gdi/Window.cpp b/DDrawCompat/Gdi/Window.cpp index 865ac17..f6b48d5 100644 --- a/DDrawCompat/Gdi/Window.cpp +++ b/DDrawCompat/Gdi/Window.cpp @@ -1,7 +1,7 @@ #include "Common/Hook.h" #include "Common/Log.h" +#include "D3dDdi/ScopedCriticalSection.h" #include "DDraw/RealPrimarySurface.h" -#include "DDraw/ScopedThreadLock.h" #include "Gdi/Gdi.h" #include "Gdi/Window.h" @@ -155,7 +155,7 @@ namespace Gdi { if (isTopLevelWindow(hwnd) && !get(hwnd)) { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; s_windows.emplace(hwnd, std::make_shared(hwnd)); return true; } @@ -196,20 +196,20 @@ namespace Gdi std::shared_ptr Window::get(HWND hwnd) { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; auto it = s_windows.find(hwnd); return it != s_windows.end() ? it->second : nullptr; } BYTE Window::getAlpha() const { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; return m_alpha; } COLORREF Window::getColorKey() const { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; return m_colorKey; } @@ -220,19 +220,19 @@ namespace Gdi Region Window::getVisibleRegion() const { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; return m_visibleRegion; } RECT Window::getWindowRect() const { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; return m_windowRect; } std::map> Window::getWindows() { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; return s_windows; } @@ -282,7 +282,7 @@ namespace Gdi void Window::remove(HWND hwnd) { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; s_windows.erase(hwnd); } @@ -301,7 +301,7 @@ namespace Gdi void Window::update() { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; if (m_isUpdating) { return; @@ -364,13 +364,13 @@ namespace Gdi void Window::updateLayeredWindowInfo(HWND hwnd, COLORREF colorKey, BYTE alpha) { - DDraw::ScopedThreadLock lock; + D3dDdi::ScopedCriticalSection lock; auto window(get(hwnd)); if (window) { window->m_colorKey = colorKey; window->m_alpha = alpha; - DDraw::RealPrimarySurface::update(); + DDraw::RealPrimarySurface::gdiUpdate(); } }