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"
|
||||
|
||||
struct _D3DDDI_ADAPTERCALLBACKS;
|
||||
struct _D3DDDI_ADAPTERFUNCS;
|
||||
struct _D3DDDI_DEVICEALLBACKS;
|
||||
struct _D3DDDI_DEVICEFUNCS;
|
||||
|
||||
template <typename Vtable>
|
||||
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 <typename Vtable, int instanceId = 0>
|
||||
class VtableHookVisitor
|
||||
{
|
||||
|
@ -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 <typename Container, typename Predicate>
|
||||
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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -1,5 +1,3 @@
|
||||
#include <atomic>
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include "Common/Hook.h"
|
||||
@ -14,8 +12,6 @@ namespace
|
||||
{
|
||||
Win32::FontSmoothing::SystemSettings g_fontSmoothingSettings = {};
|
||||
WNDPROC g_origDdWndProc = nullptr;
|
||||
std::atomic<DWORD> 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;
|
||||
|
@ -8,7 +8,6 @@ namespace DDraw
|
||||
{
|
||||
namespace ActivateAppHandler
|
||||
{
|
||||
void installHooks();
|
||||
void setCooperativeLevel(HWND hwnd, DWORD flags);
|
||||
}
|
||||
}
|
||||
|
@ -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<IDirectDraw7> dd7)
|
||||
{
|
||||
RealPrimarySurface::init();
|
||||
ActivateAppHandler::installHooks();
|
||||
|
||||
Win32::Registry::unsetValue(
|
||||
HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\DirectDraw", "EmulationOnly");
|
||||
|
@ -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<IDirectDraw4>);
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
@ -15,9 +15,8 @@ namespace DDraw
|
||||
template <typename DirectDraw>
|
||||
static HRESULT create(CompatRef<DirectDraw> dd);
|
||||
|
||||
static void disableUpdates();
|
||||
static void enableUpdates();
|
||||
static HRESULT flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags);
|
||||
static void gdiUpdate();
|
||||
static HRESULT getGammaRamp(DDGAMMARAMP* rampData);
|
||||
static CompatWeakPtr<IDirectDrawSurface7> getSurface();
|
||||
static void init();
|
||||
|
@ -8,11 +8,14 @@
|
||||
#include "DDraw/RealPrimarySurface.h"
|
||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||
#include "DDraw/Surfaces/PrimarySurfaceImpl.h"
|
||||
#include "Gdi/VirtualScreen.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
CompatWeakPtr<IDirectDrawSurface7> g_primarySurface;
|
||||
std::vector<CompatWeakPtr<IDirectDrawSurface7>> 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<PrimarySurface>());
|
||||
auto privateData(std::make_unique<PrimarySurface>());
|
||||
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<IDirectDrawSurface7>::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<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;
|
||||
}
|
||||
|
||||
@ -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<HANDLE*>(g_gdiResourceHandle));
|
||||
updateFrontResource();
|
||||
D3dDdi::Device::setGdiResourceHandle(g_frontResource);
|
||||
|
||||
Surface::restore();
|
||||
}
|
||||
|
||||
void PrimarySurface::updateFrontResource()
|
||||
{
|
||||
g_frontResource = getDriverResourceHandle(*g_primarySurface);
|
||||
}
|
||||
|
||||
void PrimarySurface::updatePalette()
|
||||
|
@ -21,13 +21,17 @@ namespace DDraw
|
||||
static CompatPtr<IDirectDrawSurface7> getBackBuffer();
|
||||
static CompatPtr<IDirectDrawSurface7> getLastSurface();
|
||||
static CompatWeakPtr<IDirectDrawSurface7> getPrimary();
|
||||
static HANDLE getFrontResource();
|
||||
static DWORD getOrigCaps();
|
||||
static void onRestore();
|
||||
static void updatePalette();
|
||||
|
||||
template <typename TSurface>
|
||||
static bool isGdiSurface(TSurface* surface);
|
||||
|
||||
static void updateFrontResource();
|
||||
|
||||
virtual void restore();
|
||||
|
||||
static CompatWeakPtr<IDirectDrawPalette> s_palette;
|
||||
static PALETTEENTRY s_paletteEntries[256];
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -34,7 +34,7 @@ namespace DDraw
|
||||
SurfaceImpl<TSurface>* getImpl() const;
|
||||
|
||||
void clearResources();
|
||||
void restore();
|
||||
virtual void restore();
|
||||
|
||||
protected:
|
||||
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<IDirectDrawSurface7>> m_impl7;
|
||||
|
||||
CompatWeakPtr<IDirectDrawSurface7> m_surface;
|
||||
std::vector<Surface*> m_attachedSurfaces;
|
||||
CompatPtr<IDirectDrawSurface7> m_lockSurface;
|
||||
std::vector<CompatWeakPtr<IDirectDrawSurface7>> m_attachedLockSurfaces;
|
||||
|
||||
private:
|
||||
template <typename TDirectDrawSurface>
|
||||
friend class SurfaceImpl;
|
||||
@ -61,9 +66,5 @@ namespace DDraw
|
||||
|
||||
DWORD m_refCount;
|
||||
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/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<TSurface>::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 <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::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 <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::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 <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::Unlock(TSurface* This, TUnlockParam lpRect)
|
||||
{
|
||||
Gdi::DDrawAccessGuard accessGuard(Gdi::ACCESS_READ, PrimarySurface::isGdiSurface(This));
|
||||
return s_origVtable.Unlock(This, lpRect);
|
||||
}
|
||||
|
||||
|
@ -1,151 +1,43 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#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<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
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
|
@ -105,7 +105,7 @@ namespace
|
||||
if (hasDisplayDcArg(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)...));
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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<WPARAM>(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<WPARAM>(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<WPARAM>(compatDc), flags);
|
||||
Gdi::Dc::releaseDc(dc);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <set>
|
||||
|
||||
#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<unsigned char*>(g_surfaceView) +
|
||||
(rect.top - g_bounds.top) * g_pitch +
|
||||
(rect.left - g_bounds.left) * g_bpp / 8;
|
||||
|
||||
auto primary(DDraw::PrimarySurface::getPrimary());
|
||||
CompatPtr<IUnknown> ddUnk;
|
||||
primary.get()->lpVtbl->GetDDInterface(primary, reinterpret_cast<void**>(&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<unsigned char*>(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<LPARAM>(&g_region));
|
||||
GetRgnBox(g_region, &g_bounds);
|
||||
|
@ -20,6 +20,7 @@ namespace Gdi
|
||||
|
||||
RECT getBounds();
|
||||
Region getRegion();
|
||||
DDSURFACEDESC2 getSurfaceDesc(const RECT& rect);
|
||||
|
||||
void init();
|
||||
bool update();
|
||||
|
@ -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();
|
||||
|
@ -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<Window>(hwnd));
|
||||
return true;
|
||||
}
|
||||
@ -196,20 +196,20 @@ namespace Gdi
|
||||
|
||||
std::shared_ptr<Window> 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<HWND, std::shared_ptr<Window>> 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user