mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Moved GDI synchronization to UMD level
Fixes deadlock when starting Rayman 2 (issue #30).
This commit is contained in:
parent
7b6b7c911c
commit
e83371afed
@ -6,7 +6,9 @@
|
|||||||
#include "DDraw/ScopedThreadLock.h"
|
#include "DDraw/ScopedThreadLock.h"
|
||||||
|
|
||||||
struct _D3DDDI_ADAPTERCALLBACKS;
|
struct _D3DDDI_ADAPTERCALLBACKS;
|
||||||
|
struct _D3DDDI_ADAPTERFUNCS;
|
||||||
struct _D3DDDI_DEVICEALLBACKS;
|
struct _D3DDDI_DEVICEALLBACKS;
|
||||||
|
struct _D3DDDI_DEVICEFUNCS;
|
||||||
|
|
||||||
template <typename Vtable>
|
template <typename Vtable>
|
||||||
class ScopedVtableFuncLock : public DDraw::ScopedThreadLock {};
|
class ScopedVtableFuncLock : public DDraw::ScopedThreadLock {};
|
||||||
@ -14,9 +16,15 @@ class ScopedVtableFuncLock : public DDraw::ScopedThreadLock {};
|
|||||||
template <>
|
template <>
|
||||||
class ScopedVtableFuncLock<_D3DDDI_ADAPTERCALLBACKS> : public D3dDdi::ScopedCriticalSection {};
|
class ScopedVtableFuncLock<_D3DDDI_ADAPTERCALLBACKS> : public D3dDdi::ScopedCriticalSection {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class ScopedVtableFuncLock<_D3DDDI_ADAPTERFUNCS> : public D3dDdi::ScopedCriticalSection {};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class ScopedVtableFuncLock<_D3DDDI_DEVICEALLBACKS> : public D3dDdi::ScopedCriticalSection {};
|
class ScopedVtableFuncLock<_D3DDDI_DEVICEALLBACKS> : public D3dDdi::ScopedCriticalSection {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class ScopedVtableFuncLock<_D3DDDI_DEVICEFUNCS> : public D3dDdi::ScopedCriticalSection {};
|
||||||
|
|
||||||
template <typename Vtable, int instanceId = 0>
|
template <typename Vtable, int instanceId = 0>
|
||||||
class VtableHookVisitor
|
class VtableHookVisitor
|
||||||
{
|
{
|
||||||
|
@ -6,34 +6,13 @@
|
|||||||
#include "D3dDdi/Device.h"
|
#include "D3dDdi/Device.h"
|
||||||
#include "D3dDdi/DeviceFuncs.h"
|
#include "D3dDdi/DeviceFuncs.h"
|
||||||
#include "D3dDdi/Resource.h"
|
#include "D3dDdi/Resource.h"
|
||||||
#include "Gdi/AccessGuard.h"
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
HANDLE g_gdiResourceHandle = nullptr;
|
HANDLE g_gdiResourceHandle = nullptr;
|
||||||
|
D3dDdi::Resource* g_gdiResource = nullptr;
|
||||||
bool g_isReadOnlyGdiLockEnabled = false;
|
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 <typename Container, typename Predicate>
|
template <typename Container, typename Predicate>
|
||||||
void erase_if(Container& container, Predicate pred)
|
void erase_if(Container& container, Predicate pred)
|
||||||
{
|
{
|
||||||
@ -69,14 +48,13 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
return it->second.blt(data);
|
return it->second.blt(data);
|
||||||
}
|
}
|
||||||
RenderGuard srcRenderGuard(*this, Gdi::ACCESS_READ, data.hSrcResource, data.SrcSubResourceIndex);
|
prepareForRendering(data.hSrcResource, data.SrcSubResourceIndex, true);
|
||||||
RenderGuard dstRenderGuard(*this, Gdi::ACCESS_WRITE, data.hDstResource, data.DstSubResourceIndex);
|
|
||||||
return m_origVtable.pfnBlt(m_device, &data);
|
return m_origVtable.pfnBlt(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::clear(const D3DDDIARG_CLEAR& data, UINT numRect, const RECT* rect)
|
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);
|
return m_origVtable.pfnClear(m_device, &data, numRect, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +65,6 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
return it->second.colorFill(data);
|
return it->second.colorFill(data);
|
||||||
}
|
}
|
||||||
RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE, data.hResource, data.SubResourceIndex);
|
|
||||||
return m_origVtable.pfnColorFill(m_device, &data);
|
return m_origVtable.pfnColorFill(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +95,17 @@ namespace D3dDdi
|
|||||||
|
|
||||||
HRESULT Device::destroyResource(HANDLE resource)
|
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)
|
if (resource == m_sharedPrimary)
|
||||||
{
|
{
|
||||||
D3DKMTReleaseProcessVidPnSourceOwners(GetCurrentProcess());
|
D3DKMTReleaseProcessVidPnSourceOwners(GetCurrentProcess());
|
||||||
@ -145,6 +133,7 @@ namespace D3dDdi
|
|||||||
if (resource == g_gdiResourceHandle)
|
if (resource == g_gdiResourceHandle)
|
||||||
{
|
{
|
||||||
g_gdiResourceHandle = nullptr;
|
g_gdiResourceHandle = nullptr;
|
||||||
|
g_gdiResource = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,55 +142,50 @@ namespace D3dDdi
|
|||||||
|
|
||||||
HRESULT Device::drawIndexedPrimitive(const D3DDDIARG_DRAWINDEXEDPRIMITIVE& data)
|
HRESULT Device::drawIndexedPrimitive(const D3DDDIARG_DRAWINDEXEDPRIMITIVE& data)
|
||||||
{
|
{
|
||||||
RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE);
|
prepareForRendering();
|
||||||
return m_origVtable.pfnDrawIndexedPrimitive(m_device, &data);
|
return m_origVtable.pfnDrawIndexedPrimitive(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::drawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2& data,
|
HRESULT Device::drawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2& data,
|
||||||
UINT indicesSize, const void* indexBuffer, const UINT* flagBuffer)
|
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);
|
return m_origVtable.pfnDrawIndexedPrimitive2(m_device, &data, indicesSize, indexBuffer, flagBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::drawPrimitive(const D3DDDIARG_DRAWPRIMITIVE& data, const UINT* 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);
|
return m_origVtable.pfnDrawPrimitive(m_device, &data, flagBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::drawPrimitive2(const D3DDDIARG_DRAWPRIMITIVE2& data)
|
HRESULT Device::drawPrimitive2(const D3DDDIARG_DRAWPRIMITIVE2& data)
|
||||||
{
|
{
|
||||||
RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE);
|
prepareForRendering();
|
||||||
return m_origVtable.pfnDrawPrimitive2(m_device, &data);
|
return m_origVtable.pfnDrawPrimitive2(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::drawRectPatch(const D3DDDIARG_DRAWRECTPATCH& data, const D3DDDIRECTPATCH_INFO* info,
|
HRESULT Device::drawRectPatch(const D3DDDIARG_DRAWRECTPATCH& data, const D3DDDIRECTPATCH_INFO* info,
|
||||||
const FLOAT* patch)
|
const FLOAT* patch)
|
||||||
{
|
{
|
||||||
RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE);
|
prepareForRendering();
|
||||||
return m_origVtable.pfnDrawRectPatch(m_device, &data, info, patch);
|
return m_origVtable.pfnDrawRectPatch(m_device, &data, info, patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::drawTriPatch(const D3DDDIARG_DRAWTRIPATCH& data, const D3DDDITRIPATCH_INFO* info,
|
HRESULT Device::drawTriPatch(const D3DDDIARG_DRAWTRIPATCH& data, const D3DDDITRIPATCH_INFO* info,
|
||||||
const FLOAT* patch)
|
const FLOAT* patch)
|
||||||
{
|
{
|
||||||
RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE);
|
prepareForRendering();
|
||||||
return m_origVtable.pfnDrawTriPatch(m_device, &data, info, patch);
|
return m_origVtable.pfnDrawTriPatch(m_device, &data, info, patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::lock(D3DDDIARG_LOCK& data)
|
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);
|
auto it = m_resources.find(data.hResource);
|
||||||
if (it != m_resources.end())
|
if (it != m_resources.end())
|
||||||
{
|
{
|
||||||
return it->second.lock(data);
|
return it->second.lock(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_origVtable.pfnLock(m_device, &data);
|
return m_origVtable.pfnLock(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,53 +201,40 @@ namespace D3dDdi
|
|||||||
|
|
||||||
HRESULT Device::present(const D3DDDIARG_PRESENT& data)
|
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);
|
return m_origVtable.pfnPresent(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::present1(D3DDDIARG_PRESENT1& 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)
|
for (UINT i = 0; i < data.SrcResources; ++i)
|
||||||
{
|
{
|
||||||
const bool isReadOnly = true;
|
prepareForRendering(data.phSrcResources[i].hResource, data.phSrcResources[i].SubResourceIndex, true);
|
||||||
prepareForRendering(data.phSrcResources[i].hResource, data.phSrcResources[i].SubResourceIndex, isReadOnly);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_origVtable.pfnPresent1(m_device, &data);
|
return m_origVtable.pfnPresent1(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::texBlt(const D3DDDIARG_TEXBLT& data)
|
HRESULT Device::texBlt(const D3DDDIARG_TEXBLT& data)
|
||||||
{
|
{
|
||||||
RenderGuard dstRenderGuard(*this, Gdi::ACCESS_WRITE, data.hDstResource);
|
prepareForRendering(data.hDstResource, UINT_MAX, false);
|
||||||
RenderGuard srcRenderGuard(*this, Gdi::ACCESS_READ, data.hSrcResource);
|
prepareForRendering(data.hSrcResource, UINT_MAX, true);
|
||||||
return m_origVtable.pfnTexBlt(m_device, &data);
|
return m_origVtable.pfnTexBlt(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::texBlt1(const D3DDDIARG_TEXBLT1& data)
|
HRESULT Device::texBlt1(const D3DDDIARG_TEXBLT1& data)
|
||||||
{
|
{
|
||||||
RenderGuard dstRenderGuard(*this, Gdi::ACCESS_WRITE, data.hDstResource);
|
prepareForRendering(data.hDstResource, UINT_MAX, false);
|
||||||
RenderGuard srcRenderGuard(*this, Gdi::ACCESS_READ, data.hSrcResource);
|
prepareForRendering(data.hSrcResource, UINT_MAX, true);
|
||||||
return m_origVtable.pfnTexBlt1(m_device, &data);
|
return m_origVtable.pfnTexBlt1(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::unlock(const D3DDDIARG_UNLOCK& 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);
|
auto it = m_resources.find(data.hResource);
|
||||||
if (it != m_resources.end())
|
if (it != m_resources.end())
|
||||||
{
|
{
|
||||||
return it->second.unlock(data);
|
return it->second.unlock(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_origVtable.pfnUnlock(m_device, &data);
|
return m_origVtable.pfnUnlock(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,6 +260,11 @@ namespace D3dDdi
|
|||||||
m_dirtyTextures.emplace(std::make_pair(resource, subResourceIndex), resource);
|
m_dirtyTextures.emplace(std::make_pair(resource, subResourceIndex), resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Resource* Device::getGdiResource()
|
||||||
|
{
|
||||||
|
return g_gdiResource;
|
||||||
|
}
|
||||||
|
|
||||||
void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly)
|
void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly)
|
||||||
{
|
{
|
||||||
auto it = m_resources.find(resource);
|
auto it = m_resources.find(resource);
|
||||||
@ -366,6 +342,11 @@ namespace D3dDdi
|
|||||||
void Device::setGdiResourceHandle(HANDLE resource)
|
void Device::setGdiResourceHandle(HANDLE resource)
|
||||||
{
|
{
|
||||||
g_gdiResourceHandle = resource;
|
g_gdiResourceHandle = resource;
|
||||||
|
g_gdiResource = getResource(resource);
|
||||||
|
if (g_gdiResource)
|
||||||
|
{
|
||||||
|
g_gdiResource->resync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::setReadOnlyGdiLock(bool enable)
|
void Device::setReadOnlyGdiLock(bool enable)
|
||||||
|
@ -56,6 +56,7 @@ namespace D3dDdi
|
|||||||
static Device& get(HANDLE device);
|
static Device& get(HANDLE device);
|
||||||
static void remove(HANDLE device);
|
static void remove(HANDLE device);
|
||||||
|
|
||||||
|
static Resource* getGdiResource();
|
||||||
static Resource* getResource(HANDLE resource);
|
static Resource* getResource(HANDLE resource);
|
||||||
static void setGdiResourceHandle(HANDLE resource);
|
static void setGdiResourceHandle(HANDLE resource);
|
||||||
static void setReadOnlyGdiLock(bool enable);
|
static void setReadOnlyGdiLock(bool enable);
|
||||||
|
@ -467,6 +467,18 @@ namespace D3dDdi
|
|||||||
return m_device.getOrigVtable().pfnBlt(m_device, &data);
|
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)
|
void Resource::setLockResource(Resource* lockResource)
|
||||||
{
|
{
|
||||||
if (!m_lockResource == !lockResource)
|
if (!m_lockResource == !lockResource)
|
||||||
|
@ -30,6 +30,7 @@ namespace D3dDdi
|
|||||||
void destroy();
|
void destroy();
|
||||||
HRESULT lock(D3DDDIARG_LOCK& data);
|
HRESULT lock(D3DDDIARG_LOCK& data);
|
||||||
void prepareForRendering(UINT subResourceIndex, bool isReadOnly);
|
void prepareForRendering(UINT subResourceIndex, bool isReadOnly);
|
||||||
|
void resync();
|
||||||
void setLockResource(Resource* lockResource);
|
void setLockResource(Resource* lockResource);
|
||||||
void setRootSurface(DDraw::Surface* rootSurface);
|
void setRootSurface(DDraw::Surface* rootSurface);
|
||||||
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
|
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#include <atomic>
|
|
||||||
|
|
||||||
#include <ddraw.h>
|
#include <ddraw.h>
|
||||||
|
|
||||||
#include "Common/Hook.h"
|
#include "Common/Hook.h"
|
||||||
@ -14,8 +12,6 @@ namespace
|
|||||||
{
|
{
|
||||||
Win32::FontSmoothing::SystemSettings g_fontSmoothingSettings = {};
|
Win32::FontSmoothing::SystemSettings g_fontSmoothingSettings = {};
|
||||||
WNDPROC g_origDdWndProc = nullptr;
|
WNDPROC g_origDdWndProc = nullptr;
|
||||||
std::atomic<DWORD> g_activateAppThreadId = 0;
|
|
||||||
HWND g_delayedFocusWnd = nullptr;
|
|
||||||
|
|
||||||
void activateApp()
|
void activateApp()
|
||||||
{
|
{
|
||||||
@ -37,7 +33,6 @@ namespace
|
|||||||
{
|
{
|
||||||
case WM_ACTIVATEAPP:
|
case WM_ACTIVATEAPP:
|
||||||
{
|
{
|
||||||
DDraw::RealPrimarySurface::disableUpdates();
|
|
||||||
isDisplayChangeNotificationEnabled = false;
|
isDisplayChangeNotificationEnabled = false;
|
||||||
if (TRUE == wParam)
|
if (TRUE == wParam)
|
||||||
{
|
{
|
||||||
@ -48,17 +43,9 @@ namespace
|
|||||||
deactivateApp();
|
deactivateApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_activateAppThreadId = GetCurrentThreadId();
|
|
||||||
g_delayedFocusWnd = nullptr;
|
|
||||||
LRESULT result = g_origDdWndProc(hwnd, uMsg, wParam, lParam);
|
LRESULT result = g_origDdWndProc(hwnd, uMsg, wParam, lParam);
|
||||||
g_activateAppThreadId = 0;
|
|
||||||
if (g_delayedFocusWnd)
|
|
||||||
{
|
|
||||||
CALL_ORIG_FUNC(SetFocus)(g_delayedFocusWnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
isDisplayChangeNotificationEnabled = true;
|
isDisplayChangeNotificationEnabled = true;
|
||||||
DDraw::RealPrimarySurface::enableUpdates();
|
|
||||||
return LOG_RESULT(result);
|
return LOG_RESULT(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,39 +62,12 @@ namespace
|
|||||||
|
|
||||||
return LOG_RESULT(g_origDdWndProc(hwnd, uMsg, wParam, lParam));
|
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 DDraw
|
||||||
{
|
{
|
||||||
namespace ActivateAppHandler
|
namespace ActivateAppHandler
|
||||||
{
|
{
|
||||||
void installHooks()
|
|
||||||
{
|
|
||||||
HOOK_FUNCTION(user32, SetFocus, setFocus);
|
|
||||||
HOOK_FUNCTION(user32, ShowWindow, showWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCooperativeLevel(HWND hwnd, DWORD flags)
|
void setCooperativeLevel(HWND hwnd, DWORD flags)
|
||||||
{
|
{
|
||||||
static bool isDdWndProcHooked = false;
|
static bool isDdWndProcHooked = false;
|
||||||
|
@ -8,7 +8,6 @@ namespace DDraw
|
|||||||
{
|
{
|
||||||
namespace ActivateAppHandler
|
namespace ActivateAppHandler
|
||||||
{
|
{
|
||||||
void installHooks();
|
|
||||||
void setCooperativeLevel(HWND hwnd, DWORD flags);
|
void setCooperativeLevel(HWND hwnd, DWORD flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "Common/CompatRef.h"
|
#include "Common/CompatRef.h"
|
||||||
#include "Common/Log.h"
|
#include "Common/Log.h"
|
||||||
#include "DDraw/ActivateAppHandler.h"
|
|
||||||
#include "DDraw/DirectDraw.h"
|
#include "DDraw/DirectDraw.h"
|
||||||
#include "DDraw/DirectDrawClipper.h"
|
#include "DDraw/DirectDrawClipper.h"
|
||||||
#include "DDraw/DirectDrawGammaControl.h"
|
#include "DDraw/DirectDrawGammaControl.h"
|
||||||
@ -95,7 +94,6 @@ namespace DDraw
|
|||||||
void installHooks(CompatPtr<IDirectDraw7> dd7)
|
void installHooks(CompatPtr<IDirectDraw7> dd7)
|
||||||
{
|
{
|
||||||
RealPrimarySurface::init();
|
RealPrimarySurface::init();
|
||||||
ActivateAppHandler::installHooks();
|
|
||||||
|
|
||||||
Win32::Registry::unsetValue(
|
Win32::Registry::unsetValue(
|
||||||
HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\DirectDraw", "EmulationOnly");
|
HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\DirectDraw", "EmulationOnly");
|
||||||
|
@ -34,7 +34,7 @@ namespace
|
|||||||
|
|
||||||
bool g_stopUpdateThread = false;
|
bool g_stopUpdateThread = false;
|
||||||
HANDLE g_updateThread = nullptr;
|
HANDLE g_updateThread = nullptr;
|
||||||
unsigned int g_disableUpdateCount = 0;
|
bool g_isGdiUpdatePending = false;
|
||||||
bool g_isFlipPending = false;
|
bool g_isFlipPending = false;
|
||||||
bool g_isPresentPending = false;
|
bool g_isPresentPending = false;
|
||||||
bool g_isUpdatePending = 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();
|
HWND presentationWindow = windowPair.second->getPresentationWindow();
|
||||||
HDC dc = GetWindowDC(presentationWindow);
|
HDC dc = GetWindowDC(presentationWindow);
|
||||||
RECT rect = windowPair.second->getWindowRect();
|
RECT rect = windowPair.second->getWindowRect();
|
||||||
@ -369,7 +369,6 @@ namespace
|
|||||||
Gdi::Region primaryRegion(D3dDdi::KernelModeThunks::getMonitorRect());
|
Gdi::Region primaryRegion(D3dDdi::KernelModeThunks::getMonitorRect());
|
||||||
bltToWindowViaGdi(&primaryRegion);
|
bltToWindowViaGdi(&primaryRegion);
|
||||||
|
|
||||||
Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_READ, DDraw::PrimarySurface::isGdiSurface(src.get()));
|
|
||||||
if (Win32::DisplayMode::getBpp() <= 8)
|
if (Win32::DisplayMode::getBpp() <= 8)
|
||||||
{
|
{
|
||||||
HDC paletteConverterDc = nullptr;
|
HDC paletteConverterDc = nullptr;
|
||||||
@ -437,12 +436,19 @@ namespace
|
|||||||
|
|
||||||
void updateNowIfNotBusy()
|
void updateNowIfNotBusy()
|
||||||
{
|
{
|
||||||
|
if (g_isGdiUpdatePending)
|
||||||
|
{
|
||||||
|
g_qpcLastUpdate = Time::queryPerformanceCounter();
|
||||||
|
g_isUpdatePending = true;
|
||||||
|
g_isGdiUpdatePending = false;
|
||||||
|
}
|
||||||
|
|
||||||
auto primary(DDraw::PrimarySurface::getPrimary());
|
auto primary(DDraw::PrimarySurface::getPrimary());
|
||||||
RECT emptyRect = {};
|
RECT emptyRect = {};
|
||||||
HRESULT result = primary ? primary->BltFast(primary, 0, 0, primary, &emptyRect, DDBLTFAST_WAIT) : DD_OK;
|
HRESULT result = primary ? primary->BltFast(primary, 0, 0, primary, &emptyRect, DDBLTFAST_WAIT) : DD_OK;
|
||||||
g_waitingForPrimaryUnlock = DDERR_SURFACEBUSY == result || DDERR_LOCKEDSURFACES == result;
|
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);
|
const auto msSinceLastUpdate = Time::qpcToMs(Time::queryPerformanceCounter() - g_qpcLastUpdate);
|
||||||
updateNow(primary, msSinceLastUpdate > Config::delayedFlipModeTimeout ? 0 : 1);
|
updateNow(primary, msSinceLastUpdate > Config::delayedFlipModeTimeout ? 0 : 1);
|
||||||
@ -472,7 +478,7 @@ namespace
|
|||||||
waitForVBlank = Time::qpcToMs(Time::queryPerformanceCounter() -
|
waitForVBlank = Time::qpcToMs(Time::queryPerformanceCounter() -
|
||||||
D3dDdi::KernelModeThunks::getQpcLastVerticalBlank()) >= msPresentDelayAfterVBlank;
|
D3dDdi::KernelModeThunks::getQpcLastVerticalBlank()) >= msPresentDelayAfterVBlank;
|
||||||
|
|
||||||
if (waitForVBlank && g_isUpdatePending && 0 == g_disableUpdateCount && !isPresentPending())
|
if (waitForVBlank && (g_isUpdatePending || g_isGdiUpdatePending) && !isPresentPending())
|
||||||
{
|
{
|
||||||
updateNowIfNotBusy();
|
updateNowIfNotBusy();
|
||||||
}
|
}
|
||||||
@ -532,18 +538,6 @@ namespace DDraw
|
|||||||
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw4>);
|
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw4>);
|
||||||
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw7>);
|
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw7>);
|
||||||
|
|
||||||
void RealPrimarySurface::disableUpdates()
|
|
||||||
{
|
|
||||||
DDraw::ScopedThreadLock lock;
|
|
||||||
--g_disableUpdateCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RealPrimarySurface::enableUpdates()
|
|
||||||
{
|
|
||||||
DDraw::ScopedThreadLock lock;
|
|
||||||
++g_disableUpdateCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT RealPrimarySurface::flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags)
|
HRESULT RealPrimarySurface::flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
DDraw::ScopedThreadLock lock;
|
||||||
@ -587,6 +581,11 @@ namespace DDraw
|
|||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RealPrimarySurface::gdiUpdate()
|
||||||
|
{
|
||||||
|
g_isGdiUpdatePending = true;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT RealPrimarySurface::getGammaRamp(DDGAMMARAMP* rampData)
|
HRESULT RealPrimarySurface::getGammaRamp(DDGAMMARAMP* rampData)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
DDraw::ScopedThreadLock lock;
|
||||||
|
@ -15,9 +15,8 @@ namespace DDraw
|
|||||||
template <typename DirectDraw>
|
template <typename DirectDraw>
|
||||||
static HRESULT create(CompatRef<DirectDraw> dd);
|
static HRESULT create(CompatRef<DirectDraw> dd);
|
||||||
|
|
||||||
static void disableUpdates();
|
|
||||||
static void enableUpdates();
|
|
||||||
static HRESULT flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags);
|
static HRESULT flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags);
|
||||||
|
static void gdiUpdate();
|
||||||
static HRESULT getGammaRamp(DDGAMMARAMP* rampData);
|
static HRESULT getGammaRamp(DDGAMMARAMP* rampData);
|
||||||
static CompatWeakPtr<IDirectDrawSurface7> getSurface();
|
static CompatWeakPtr<IDirectDrawSurface7> getSurface();
|
||||||
static void init();
|
static void init();
|
||||||
|
@ -8,11 +8,14 @@
|
|||||||
#include "DDraw/RealPrimarySurface.h"
|
#include "DDraw/RealPrimarySurface.h"
|
||||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||||
#include "DDraw/Surfaces/PrimarySurfaceImpl.h"
|
#include "DDraw/Surfaces/PrimarySurfaceImpl.h"
|
||||||
|
#include "Gdi/VirtualScreen.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
CompatWeakPtr<IDirectDrawSurface7> g_primarySurface;
|
CompatWeakPtr<IDirectDrawSurface7> g_primarySurface;
|
||||||
|
std::vector<CompatWeakPtr<IDirectDrawSurface7>> g_lockBackBuffers;
|
||||||
HANDLE g_gdiResourceHandle = nullptr;
|
HANDLE g_gdiResourceHandle = nullptr;
|
||||||
|
HANDLE g_frontResource = nullptr;
|
||||||
DWORD g_origCaps = 0;
|
DWORD g_origCaps = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,11 +26,18 @@ namespace DDraw
|
|||||||
LOG_FUNC("PrimarySurface::~PrimarySurface");
|
LOG_FUNC("PrimarySurface::~PrimarySurface");
|
||||||
|
|
||||||
g_gdiResourceHandle = nullptr;
|
g_gdiResourceHandle = nullptr;
|
||||||
|
g_frontResource = nullptr;
|
||||||
g_primarySurface = nullptr;
|
g_primarySurface = nullptr;
|
||||||
g_origCaps = 0;
|
g_origCaps = 0;
|
||||||
s_palette = nullptr;
|
s_palette = nullptr;
|
||||||
ZeroMemory(&s_paletteEntries, sizeof(s_paletteEntries));
|
ZeroMemory(&s_paletteEntries, sizeof(s_paletteEntries));
|
||||||
|
|
||||||
|
for (auto& lockBuffer : g_lockBackBuffers)
|
||||||
|
{
|
||||||
|
lockBuffer.release();
|
||||||
|
}
|
||||||
|
g_lockBackBuffers.clear();
|
||||||
|
|
||||||
DDraw::RealPrimarySurface::release();
|
DDraw::RealPrimarySurface::release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +60,9 @@ namespace DDraw
|
|||||||
desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
|
desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
|
||||||
desc.ddpfPixelFormat = dm.ddpfPixelFormat;
|
desc.ddpfPixelFormat = dm.ddpfPixelFormat;
|
||||||
|
|
||||||
result = Surface::create(dd, desc, surface, std::make_unique<PrimarySurface>());
|
auto privateData(std::make_unique<PrimarySurface>());
|
||||||
|
auto data = privateData.get();
|
||||||
|
result = Surface::create(dd, desc, surface, std::move(privateData));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
Compat::Log() << "ERROR: Failed to create the compat primary surface: " << Compat::hex(result);
|
Compat::Log() << "ERROR: Failed to create the compat primary surface: " << Compat::hex(result);
|
||||||
@ -58,11 +70,32 @@ namespace DDraw
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_primarySurface = CompatPtr<IDirectDrawSurface7>::from(surface);
|
|
||||||
g_origCaps = origCaps;
|
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<TSurface> 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<TSurface> lockBuffer;
|
||||||
|
dd->CreateSurface(&dd, &desc, &lockBuffer.getRef(), nullptr);
|
||||||
|
if (lockBuffer)
|
||||||
|
{
|
||||||
|
g_lockBackBuffers.push_back(CompatPtr<IDirectDrawSurface7>::from(lockBuffer.get()).detach());
|
||||||
|
data->m_attachedLockSurfaces.push_back(g_lockBackBuffers.back());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data->restore();
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,6 +185,11 @@ namespace DDraw
|
|||||||
return g_primarySurface;
|
return g_primarySurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HANDLE PrimarySurface::getFrontResource()
|
||||||
|
{
|
||||||
|
return g_frontResource;
|
||||||
|
}
|
||||||
|
|
||||||
DWORD PrimarySurface::getOrigCaps()
|
DWORD PrimarySurface::getOrigCaps()
|
||||||
{
|
{
|
||||||
return g_origCaps;
|
return g_origCaps;
|
||||||
@ -169,10 +207,28 @@ namespace DDraw
|
|||||||
template bool PrimarySurface::isGdiSurface(IDirectDrawSurface4*);
|
template bool PrimarySurface::isGdiSurface(IDirectDrawSurface4*);
|
||||||
template bool PrimarySurface::isGdiSurface(IDirectDrawSurface7*);
|
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);
|
g_gdiResourceHandle = getRuntimeResourceHandle(*g_primarySurface);
|
||||||
D3dDdi::Device::setGdiResourceHandle(*reinterpret_cast<HANDLE*>(g_gdiResourceHandle));
|
updateFrontResource();
|
||||||
|
D3dDdi::Device::setGdiResourceHandle(g_frontResource);
|
||||||
|
|
||||||
|
Surface::restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimarySurface::updateFrontResource()
|
||||||
|
{
|
||||||
|
g_frontResource = getDriverResourceHandle(*g_primarySurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrimarySurface::updatePalette()
|
void PrimarySurface::updatePalette()
|
||||||
|
@ -21,13 +21,17 @@ namespace DDraw
|
|||||||
static CompatPtr<IDirectDrawSurface7> getBackBuffer();
|
static CompatPtr<IDirectDrawSurface7> getBackBuffer();
|
||||||
static CompatPtr<IDirectDrawSurface7> getLastSurface();
|
static CompatPtr<IDirectDrawSurface7> getLastSurface();
|
||||||
static CompatWeakPtr<IDirectDrawSurface7> getPrimary();
|
static CompatWeakPtr<IDirectDrawSurface7> getPrimary();
|
||||||
|
static HANDLE getFrontResource();
|
||||||
static DWORD getOrigCaps();
|
static DWORD getOrigCaps();
|
||||||
static void onRestore();
|
|
||||||
static void updatePalette();
|
static void updatePalette();
|
||||||
|
|
||||||
template <typename TSurface>
|
template <typename TSurface>
|
||||||
static bool isGdiSurface(TSurface* surface);
|
static bool isGdiSurface(TSurface* surface);
|
||||||
|
|
||||||
|
static void updateFrontResource();
|
||||||
|
|
||||||
|
virtual void restore();
|
||||||
|
|
||||||
static CompatWeakPtr<IDirectDrawPalette> s_palette;
|
static CompatWeakPtr<IDirectDrawPalette> s_palette;
|
||||||
static PALETTEENTRY s_paletteEntries[256];
|
static PALETTEENTRY s_paletteEntries[256];
|
||||||
|
|
||||||
|
@ -134,6 +134,7 @@ namespace DDraw
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrimarySurface::updateFrontResource();
|
||||||
return RealPrimarySurface::flip(surfaceTargetOverride, dwFlags);
|
return RealPrimarySurface::flip(surfaceTargetOverride, dwFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,11 +209,7 @@ namespace DDraw
|
|||||||
result = RealPrimarySurface::restore();
|
result = RealPrimarySurface::restore();
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
result = SurfaceImpl::Restore(This);
|
return SurfaceImpl::Restore(This);
|
||||||
if (SUCCEEDED(result))
|
|
||||||
{
|
|
||||||
PrimarySurface::onRestore();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -213,8 +213,6 @@ namespace DDraw
|
|||||||
return LOG_RESULT(nullptr);
|
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_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
|
||||||
desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ namespace DDraw
|
|||||||
SurfaceImpl<TSurface>* getImpl() const;
|
SurfaceImpl<TSurface>* getImpl() const;
|
||||||
|
|
||||||
void clearResources();
|
void clearResources();
|
||||||
void restore();
|
virtual void restore();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void attach(CompatRef<IDirectDrawSurface7> dds, std::unique_ptr<Surface> privateData);
|
static void attach(CompatRef<IDirectDrawSurface7> dds, std::unique_ptr<Surface> privateData);
|
||||||
@ -48,6 +48,11 @@ namespace DDraw
|
|||||||
std::unique_ptr<SurfaceImpl<IDirectDrawSurface4>> m_impl4;
|
std::unique_ptr<SurfaceImpl<IDirectDrawSurface4>> m_impl4;
|
||||||
std::unique_ptr<SurfaceImpl<IDirectDrawSurface7>> m_impl7;
|
std::unique_ptr<SurfaceImpl<IDirectDrawSurface7>> m_impl7;
|
||||||
|
|
||||||
|
CompatWeakPtr<IDirectDrawSurface7> m_surface;
|
||||||
|
std::vector<Surface*> m_attachedSurfaces;
|
||||||
|
CompatPtr<IDirectDrawSurface7> m_lockSurface;
|
||||||
|
std::vector<CompatWeakPtr<IDirectDrawSurface7>> m_attachedLockSurfaces;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename TDirectDrawSurface>
|
template <typename TDirectDrawSurface>
|
||||||
friend class SurfaceImpl;
|
friend class SurfaceImpl;
|
||||||
@ -61,9 +66,5 @@ namespace DDraw
|
|||||||
|
|
||||||
DWORD m_refCount;
|
DWORD m_refCount;
|
||||||
Surface* m_rootSurface;
|
Surface* m_rootSurface;
|
||||||
CompatWeakPtr<IDirectDrawSurface7> m_surface;
|
|
||||||
std::vector<Surface*> m_attachedSurfaces;
|
|
||||||
CompatPtr<IDirectDrawSurface7> m_lockSurface;
|
|
||||||
std::vector<CompatWeakPtr<IDirectDrawSurface7>> m_attachedLockSurfaces;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||||
#include "DDraw/Surfaces/Surface.h"
|
#include "DDraw/Surfaces/Surface.h"
|
||||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||||
#include "Gdi/AccessGuard.h"
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -36,9 +35,6 @@ namespace DDraw
|
|||||||
{
|
{
|
||||||
return DDERR_WASSTILLDRAWING;
|
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);
|
return s_origVtable.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,8 +42,6 @@ namespace DDraw
|
|||||||
HRESULT SurfaceImpl<TSurface>::BltFast(
|
HRESULT SurfaceImpl<TSurface>::BltFast(
|
||||||
TSurface* This, DWORD dwX, DWORD dwY, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans)
|
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);
|
return s_origVtable.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,18 +75,11 @@ namespace DDraw
|
|||||||
template <typename TSurface>
|
template <typename TSurface>
|
||||||
HRESULT SurfaceImpl<TSurface>::GetDC(TSurface* This, HDC* lphDC)
|
HRESULT SurfaceImpl<TSurface>::GetDC(TSurface* This, HDC* lphDC)
|
||||||
{
|
{
|
||||||
HRESULT result = DD_OK;
|
HRESULT result = s_origVtable.GetDC(This, lphDC);
|
||||||
|
|
||||||
{
|
|
||||||
Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
|
||||||
result = s_origVtable.GetDC(This, lphDC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
RealPrimarySurface::waitForFlip(m_data);
|
RealPrimarySurface::waitForFlip(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,8 +130,6 @@ namespace DDraw
|
|||||||
return DDERR_WASSTILLDRAWING;
|
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);
|
HRESULT result = s_origVtable.Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
|
||||||
if (DDERR_SURFACELOST == result)
|
if (DDERR_SURFACELOST == result)
|
||||||
{
|
{
|
||||||
@ -164,7 +149,6 @@ namespace DDraw
|
|||||||
template <typename TSurface>
|
template <typename TSurface>
|
||||||
HRESULT SurfaceImpl<TSurface>::ReleaseDC(TSurface* This, HDC hDC)
|
HRESULT SurfaceImpl<TSurface>::ReleaseDC(TSurface* This, HDC hDC)
|
||||||
{
|
{
|
||||||
Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_READ, PrimarySurface::isGdiSurface(This));
|
|
||||||
return s_origVtable.ReleaseDC(This, hDC);
|
return s_origVtable.ReleaseDC(This, hDC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +172,6 @@ namespace DDraw
|
|||||||
template <typename TSurface>
|
template <typename TSurface>
|
||||||
HRESULT SurfaceImpl<TSurface>::Unlock(TSurface* This, TUnlockParam lpRect)
|
HRESULT SurfaceImpl<TSurface>::Unlock(TSurface* This, TUnlockParam lpRect)
|
||||||
{
|
{
|
||||||
Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_READ, PrimarySurface::isGdiSurface(This));
|
|
||||||
return s_origVtable.Unlock(This, lpRect);
|
return s_origVtable.Unlock(This, lpRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,151 +1,43 @@
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#include "D3dDdi/Device.h"
|
||||||
|
#include "D3dDdi/Resource.h"
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
#include "D3dDdi/KernelModeThunks.h"
|
|
||||||
#include "DDraw/RealPrimarySurface.h"
|
#include "DDraw/RealPrimarySurface.h"
|
||||||
#include "DDraw/ScopedThreadLock.h"
|
|
||||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||||
#include "Gdi/AccessGuard.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<IDirectDrawClipper> 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
|
namespace Gdi
|
||||||
{
|
{
|
||||||
AccessGuard::AccessGuard(User user, Access access, bool condition)
|
AccessGuard::AccessGuard(Access access, bool condition)
|
||||||
: m_user(user)
|
: m_access(access)
|
||||||
, m_access(access)
|
|
||||||
, m_condition(condition)
|
, m_condition(condition)
|
||||||
{
|
{
|
||||||
if (m_condition)
|
if (m_condition)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
if (g_isSyncing)
|
auto gdiResource = D3dDdi::Device::getGdiResource();
|
||||||
|
if (gdiResource)
|
||||||
{
|
{
|
||||||
m_condition = false;
|
D3DDDIARG_LOCK lockData = {};
|
||||||
return;
|
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()
|
AccessGuard::~AccessGuard()
|
||||||
{
|
{
|
||||||
if (m_condition)
|
if (m_condition && ACCESS_WRITE == m_access)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
endAccess(m_user, m_access);
|
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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
namespace D3dDdi
|
||||||
|
{
|
||||||
|
class Resource;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Gdi
|
namespace Gdi
|
||||||
{
|
{
|
||||||
enum Access
|
enum Access
|
||||||
@ -8,33 +13,14 @@ namespace Gdi
|
|||||||
ACCESS_WRITE
|
ACCESS_WRITE
|
||||||
};
|
};
|
||||||
|
|
||||||
enum User
|
|
||||||
{
|
|
||||||
USER_DDRAW,
|
|
||||||
USER_GDI
|
|
||||||
};
|
|
||||||
|
|
||||||
class AccessGuard
|
class AccessGuard
|
||||||
{
|
{
|
||||||
protected:
|
public:
|
||||||
AccessGuard(User user, Access access, bool condition = true);
|
AccessGuard(Access access, bool condition = true);
|
||||||
~AccessGuard();
|
~AccessGuard();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
User m_user;
|
|
||||||
Access m_access;
|
Access m_access;
|
||||||
bool m_condition;
|
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);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "Common/Hook.h"
|
#include "Common/Hook.h"
|
||||||
#include "Common/Time.h"
|
#include "Common/Time.h"
|
||||||
#include "DDraw/ScopedThreadLock.h"
|
#include "D3dDdi/ScopedCriticalSection.h"
|
||||||
#include "Gdi/Caret.h"
|
#include "Gdi/Caret.h"
|
||||||
|
|
||||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
@ -34,7 +34,6 @@ namespace
|
|||||||
{
|
{
|
||||||
if (OBJID_CARET == idObject)
|
if (OBJID_CARET == idObject)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
|
||||||
updateCaret(GetWindowThreadProcessId(hwnd, nullptr));
|
updateCaret(GetWindowThreadProcessId(hwnd, nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +63,7 @@ namespace
|
|||||||
|
|
||||||
void updateCaret(DWORD threadId)
|
void updateCaret(DWORD threadId)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
if (g_caret.isDrawn)
|
if (g_caret.isDrawn)
|
||||||
{
|
{
|
||||||
drawCaret();
|
drawCaret();
|
||||||
@ -87,7 +86,7 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
void blink()
|
void blink()
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
if (!g_caret.isVisible)
|
if (!g_caret.isVisible)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "Common/Hook.h"
|
#include "Common/Hook.h"
|
||||||
#include "Common/Log.h"
|
#include "Common/Log.h"
|
||||||
#include "Common/ScopedCriticalSection.h"
|
#include "Common/ScopedCriticalSection.h"
|
||||||
#include "DDraw/ScopedThreadLock.h"
|
#include "D3dDdi/ScopedCriticalSection.h"
|
||||||
#include "Gdi/Dc.h"
|
#include "Gdi/Dc.h"
|
||||||
#include "Gdi/DcCache.h"
|
#include "Gdi/DcCache.h"
|
||||||
#include "Gdi/Gdi.h"
|
#include "Gdi/Gdi.h"
|
||||||
@ -185,7 +185,7 @@ namespace Gdi
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DDraw::ScopedThreadLock ddLock;
|
D3dDdi::ScopedCriticalSection driverLock;
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
Compat::ScopedCriticalSection lock(g_cs);
|
||||||
auto it = g_origDcToCompatDc.find(origDc);
|
auto it = g_origDcToCompatDc.find(origDc);
|
||||||
if (it != g_origDcToCompatDc.end())
|
if (it != g_origDcToCompatDc.end())
|
||||||
|
@ -105,7 +105,7 @@ namespace
|
|||||||
if (hasDisplayDcArg(params...))
|
if (hasDisplayDcArg(params...))
|
||||||
{
|
{
|
||||||
const bool isReadOnlyAccess = !hasDisplayDcArg(getDestinationDc<OrigFuncPtr, origFunc>(params...));
|
const bool isReadOnlyAccess = !hasDisplayDcArg(getDestinationDc<OrigFuncPtr, origFunc>(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<OrigFuncPtr, origFunc>()(replaceDc(params)...));
|
return LOG_RESULT(Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(replaceDc(params)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ namespace
|
|||||||
}
|
}
|
||||||
else
|
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));
|
return LOG_RESULT(CALL_ORIG_FUNC(ExtTextOutW)(replaceDc(hdc), x, y, options, lprect, lpString, c, lpDx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Common/Hook.h"
|
#include "Common/Hook.h"
|
||||||
#include "Common/Log.h"
|
#include "Common/Log.h"
|
||||||
|
#include "D3dDdi/ScopedCriticalSection.h"
|
||||||
#include "DDraw/RealPrimarySurface.h"
|
#include "DDraw/RealPrimarySurface.h"
|
||||||
#include "Gdi/AccessGuard.h"
|
#include "Gdi/AccessGuard.h"
|
||||||
#include "Gdi/Dc.h"
|
#include "Gdi/Dc.h"
|
||||||
@ -254,7 +255,7 @@ namespace
|
|||||||
HDC compatDc = Gdi::Dc::getDc(dc);
|
HDC compatDc = Gdi::Dc::getDc(dc);
|
||||||
if (compatDc)
|
if (compatDc)
|
||||||
{
|
{
|
||||||
Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
||||||
result = CallWindowProc(origWndProc, hwnd, WM_ERASEBKGND, reinterpret_cast<WPARAM>(compatDc), 0);
|
result = CallWindowProc(origWndProc, hwnd, WM_ERASEBKGND, reinterpret_cast<WPARAM>(compatDc), 0);
|
||||||
Gdi::Dc::releaseDc(dc);
|
Gdi::Dc::releaseDc(dc);
|
||||||
return result;
|
return result;
|
||||||
@ -276,7 +277,7 @@ namespace
|
|||||||
|
|
||||||
if (compatDc)
|
if (compatDc)
|
||||||
{
|
{
|
||||||
Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
||||||
Gdi::TitleBar titleBar(hwnd, compatDc);
|
Gdi::TitleBar titleBar(hwnd, compatDc);
|
||||||
titleBar.drawAll();
|
titleBar.drawAll();
|
||||||
titleBar.excludeFromClipRegion();
|
titleBar.excludeFromClipRegion();
|
||||||
@ -301,14 +302,13 @@ namespace
|
|||||||
return CallWindowProc(origWndProc, hwnd, WM_PAINT, 0, 0);
|
return CallWindowProc(origWndProc, hwnd, WM_PAINT, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
DDraw::ScopedThreadLock lock;
|
|
||||||
PAINTSTRUCT paint = {};
|
PAINTSTRUCT paint = {};
|
||||||
HDC dc = BeginPaint(hwnd, &paint);
|
HDC dc = BeginPaint(hwnd, &paint);
|
||||||
HDC compatDc = Gdi::Dc::getDc(dc);
|
HDC compatDc = Gdi::Dc::getDc(dc);
|
||||||
|
|
||||||
if (compatDc)
|
if (compatDc)
|
||||||
{
|
{
|
||||||
Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
||||||
CallWindowProc(origWndProc, hwnd, WM_PRINTCLIENT,
|
CallWindowProc(origWndProc, hwnd, WM_PRINTCLIENT,
|
||||||
reinterpret_cast<WPARAM>(compatDc), PRF_CLIENT);
|
reinterpret_cast<WPARAM>(compatDc), PRF_CLIENT);
|
||||||
Gdi::Dc::releaseDc(dc);
|
Gdi::Dc::releaseDc(dc);
|
||||||
@ -329,7 +329,7 @@ namespace
|
|||||||
HDC compatDc = Gdi::Dc::getDc(dc);
|
HDC compatDc = Gdi::Dc::getDc(dc);
|
||||||
if (compatDc)
|
if (compatDc)
|
||||||
{
|
{
|
||||||
Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
||||||
result = CallWindowProc(origWndProc, hwnd, msg, reinterpret_cast<WPARAM>(compatDc), flags);
|
result = CallWindowProc(origWndProc, hwnd, msg, reinterpret_cast<WPARAM>(compatDc), flags);
|
||||||
Gdi::Dc::releaseDc(dc);
|
Gdi::Dc::releaseDc(dc);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "Common/Hook.h"
|
#include "Common/Hook.h"
|
||||||
#include "Common/Log.h"
|
#include "Common/Log.h"
|
||||||
#include "DDraw/ScopedThreadLock.h"
|
#include "D3dDdi/ScopedCriticalSection.h"
|
||||||
#include "Gdi/Gdi.h"
|
#include "Gdi/Gdi.h"
|
||||||
#include "Gdi/ScrollFunctions.h"
|
#include "Gdi/ScrollFunctions.h"
|
||||||
#include "Gdi/Window.h"
|
#include "Gdi/Window.h"
|
||||||
@ -52,7 +52,7 @@ namespace Gdi
|
|||||||
|
|
||||||
void updateScrolledWindow(HWND hwnd)
|
void updateScrolledWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
auto window(Gdi::Window::get(hwnd));
|
auto window(Gdi::Window::get(hwnd));
|
||||||
UINT flags = RDW_ERASE | RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW;
|
UINT flags = RDW_ERASE | RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW;
|
||||||
if (!window || window->getPresentationWindow() != hwnd)
|
if (!window || window->getPresentationWindow() != hwnd)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "Common/ScopedCriticalSection.h"
|
#include "Common/ScopedCriticalSection.h"
|
||||||
|
#include "D3dDdi/Device.h"
|
||||||
|
#include "D3dDdi/ScopedCriticalSection.h"
|
||||||
#include "DDraw/DirectDraw.h"
|
#include "DDraw/DirectDraw.h"
|
||||||
#include "DDraw/ScopedThreadLock.h"
|
#include "DDraw/ScopedThreadLock.h"
|
||||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||||
@ -119,24 +121,12 @@ namespace Gdi
|
|||||||
DDraw::ScopedThreadLock ddLock;
|
DDraw::ScopedThreadLock ddLock;
|
||||||
Compat::ScopedCriticalSection lock(g_cs);
|
Compat::ScopedCriticalSection lock(g_cs);
|
||||||
|
|
||||||
if (rect.left < g_bounds.left || rect.top < g_bounds.top ||
|
auto desc = getSurfaceDesc(rect);
|
||||||
rect.right > g_bounds.right || rect.bottom > g_bounds.bottom)
|
if (!desc.lpSurface)
|
||||||
{
|
{
|
||||||
return nullptr;
|
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<unsigned char*>(g_surfaceView) +
|
|
||||||
(rect.top - g_bounds.top) * g_pitch +
|
|
||||||
(rect.left - g_bounds.left) * g_bpp / 8;
|
|
||||||
|
|
||||||
auto primary(DDraw::PrimarySurface::getPrimary());
|
auto primary(DDraw::PrimarySurface::getPrimary());
|
||||||
CompatPtr<IUnknown> ddUnk;
|
CompatPtr<IUnknown> ddUnk;
|
||||||
primary.get()->lpVtbl->GetDDInterface(primary, reinterpret_cast<void**>(&ddUnk.getRef()));
|
primary.get()->lpVtbl->GetDDInterface(primary, reinterpret_cast<void**>(&ddUnk.getRef()));
|
||||||
@ -172,6 +162,29 @@ namespace Gdi
|
|||||||
return g_region;
|
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<unsigned char*>(g_surfaceView) +
|
||||||
|
(rect.top - g_bounds.top) * g_pitch +
|
||||||
|
(rect.left - g_bounds.left) * g_bpp / 8;
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
@ -192,6 +205,11 @@ namespace Gdi
|
|||||||
|
|
||||||
prevDisplaySettingsUniqueness = currentDisplaySettingsUniqueness;
|
prevDisplaySettingsUniqueness = currentDisplaySettingsUniqueness;
|
||||||
|
|
||||||
|
{
|
||||||
|
D3dDdi::ScopedCriticalSection driverLock;
|
||||||
|
D3dDdi::Device::setGdiResourceHandle(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
g_region = Region();
|
g_region = Region();
|
||||||
EnumDisplayMonitors(nullptr, nullptr, addMonitorRectToRegion, reinterpret_cast<LPARAM>(&g_region));
|
EnumDisplayMonitors(nullptr, nullptr, addMonitorRectToRegion, reinterpret_cast<LPARAM>(&g_region));
|
||||||
GetRgnBox(g_region, &g_bounds);
|
GetRgnBox(g_region, &g_bounds);
|
||||||
|
@ -20,6 +20,7 @@ namespace Gdi
|
|||||||
|
|
||||||
RECT getBounds();
|
RECT getBounds();
|
||||||
Region getRegion();
|
Region getRegion();
|
||||||
|
DDSURFACEDESC2 getSurfaceDesc(const RECT& rect);
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
bool update();
|
bool update();
|
||||||
|
@ -139,7 +139,7 @@ namespace
|
|||||||
HDC compatDc = Gdi::Dc::getDc(windowDc);
|
HDC compatDc = Gdi::Dc::getDc(windowDc);
|
||||||
if (compatDc)
|
if (compatDc)
|
||||||
{
|
{
|
||||||
Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
||||||
if (OBJID_TITLEBAR == idObject)
|
if (OBJID_TITLEBAR == idObject)
|
||||||
{
|
{
|
||||||
Gdi::TitleBar(hwnd, compatDc).drawButtons();
|
Gdi::TitleBar(hwnd, compatDc).drawButtons();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "Common/Hook.h"
|
#include "Common/Hook.h"
|
||||||
#include "Common/Log.h"
|
#include "Common/Log.h"
|
||||||
|
#include "D3dDdi/ScopedCriticalSection.h"
|
||||||
#include "DDraw/RealPrimarySurface.h"
|
#include "DDraw/RealPrimarySurface.h"
|
||||||
#include "DDraw/ScopedThreadLock.h"
|
|
||||||
#include "Gdi/Gdi.h"
|
#include "Gdi/Gdi.h"
|
||||||
#include "Gdi/Window.h"
|
#include "Gdi/Window.h"
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
if (isTopLevelWindow(hwnd) && !get(hwnd))
|
if (isTopLevelWindow(hwnd) && !get(hwnd))
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
s_windows.emplace(hwnd, std::make_shared<Window>(hwnd));
|
s_windows.emplace(hwnd, std::make_shared<Window>(hwnd));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -196,20 +196,20 @@ namespace Gdi
|
|||||||
|
|
||||||
std::shared_ptr<Window> Window::get(HWND hwnd)
|
std::shared_ptr<Window> Window::get(HWND hwnd)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
auto it = s_windows.find(hwnd);
|
auto it = s_windows.find(hwnd);
|
||||||
return it != s_windows.end() ? it->second : nullptr;
|
return it != s_windows.end() ? it->second : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BYTE Window::getAlpha() const
|
BYTE Window::getAlpha() const
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
return m_alpha;
|
return m_alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
COLORREF Window::getColorKey() const
|
COLORREF Window::getColorKey() const
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
return m_colorKey;
|
return m_colorKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,19 +220,19 @@ namespace Gdi
|
|||||||
|
|
||||||
Region Window::getVisibleRegion() const
|
Region Window::getVisibleRegion() const
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
return m_visibleRegion;
|
return m_visibleRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT Window::getWindowRect() const
|
RECT Window::getWindowRect() const
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
return m_windowRect;
|
return m_windowRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<HWND, std::shared_ptr<Window>> Window::getWindows()
|
std::map<HWND, std::shared_ptr<Window>> Window::getWindows()
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
return s_windows;
|
return s_windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +282,7 @@ namespace Gdi
|
|||||||
|
|
||||||
void Window::remove(HWND hwnd)
|
void Window::remove(HWND hwnd)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
s_windows.erase(hwnd);
|
s_windows.erase(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +301,7 @@ namespace Gdi
|
|||||||
|
|
||||||
void Window::update()
|
void Window::update()
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
if (m_isUpdating)
|
if (m_isUpdating)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -364,13 +364,13 @@ namespace Gdi
|
|||||||
|
|
||||||
void Window::updateLayeredWindowInfo(HWND hwnd, COLORREF colorKey, BYTE alpha)
|
void Window::updateLayeredWindowInfo(HWND hwnd, COLORREF colorKey, BYTE alpha)
|
||||||
{
|
{
|
||||||
DDraw::ScopedThreadLock lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
auto window(get(hwnd));
|
auto window(get(hwnd));
|
||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
window->m_colorKey = colorKey;
|
window->m_colorKey = colorKey;
|
||||||
window->m_alpha = alpha;
|
window->m_alpha = alpha;
|
||||||
DDraw::RealPrimarySurface::update();
|
DDraw::RealPrimarySurface::gdiUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user