1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Improved GetPixel performance via DDLOCK_READONLY

Reduces Diablo II startup time.
This commit is contained in:
narzoul 2016-05-21 15:21:43 +02:00
parent b78ea774d7
commit cf08f10162
3 changed files with 40 additions and 8 deletions

View File

@ -17,6 +17,7 @@ namespace
{ {
std::atomic<int> g_disableEmulationCount = 0; std::atomic<int> g_disableEmulationCount = 0;
DWORD g_renderingRefCount = 0; DWORD g_renderingRefCount = 0;
DWORD g_ddLockFlags = 0;
DWORD g_ddLockThreadRenderingRefCount = 0; DWORD g_ddLockThreadRenderingRefCount = 0;
DWORD g_ddLockThreadId = 0; DWORD g_ddLockThreadId = 0;
HANDLE g_ddUnlockBeginEvent = nullptr; HANDLE g_ddUnlockBeginEvent = nullptr;
@ -53,16 +54,22 @@ namespace
return TRUE; return TRUE;
} }
bool lockPrimarySurface() bool lockPrimarySurface(DWORD lockFlags)
{ {
DDSURFACEDESC2 desc = {}; DDSURFACEDESC2 desc = {};
desc.dwSize = sizeof(desc); desc.dwSize = sizeof(desc);
auto primary(CompatPrimarySurface::getPrimary()); auto primary(CompatPrimarySurface::getPrimary());
if (FAILED(primary->Lock(primary, nullptr, &desc, DDLOCK_WAIT, nullptr))) if (FAILED(primary->Lock(primary, nullptr, &desc, lockFlags | DDLOCK_WAIT, nullptr)))
{ {
return false; return false;
} }
g_ddLockFlags = lockFlags;
if (0 != lockFlags)
{
EnterCriticalSection(&CompatGdi::g_gdiCriticalSection);
}
g_ddLockThreadId = GetCurrentThreadId(); g_ddLockThreadId = GetCurrentThreadId();
CompatGdiDcCache::setDdLockThreadId(g_ddLockThreadId); CompatGdiDcCache::setDdLockThreadId(g_ddLockThreadId);
CompatGdiDcCache::setSurfaceMemory(desc.lpSurface, desc.lPitch); CompatGdiDcCache::setSurfaceMemory(desc.lpSurface, desc.lPitch);
@ -74,8 +81,17 @@ namespace
GdiFlush(); GdiFlush();
auto primary(CompatPrimarySurface::getPrimary()); auto primary(CompatPrimarySurface::getPrimary());
primary->Unlock(primary, nullptr); primary->Unlock(primary, nullptr);
RealPrimarySurface::invalidate(nullptr); if (DDLOCK_READONLY != g_ddLockFlags)
RealPrimarySurface::update(); {
RealPrimarySurface::invalidate(nullptr);
RealPrimarySurface::update();
}
if (0 != g_ddLockFlags)
{
LeaveCriticalSection(&CompatGdi::g_gdiCriticalSection);
}
g_ddLockFlags = 0;
Compat::origProcs.ReleaseDDThreadLock(); Compat::origProcs.ReleaseDDThreadLock();
} }
@ -85,7 +101,7 @@ namespace CompatGdi
{ {
CRITICAL_SECTION g_gdiCriticalSection; CRITICAL_SECTION g_gdiCriticalSection;
bool beginGdiRendering() bool beginGdiRendering(DWORD lockFlags)
{ {
if (!isEmulationEnabled()) if (!isEmulationEnabled())
{ {
@ -99,7 +115,7 @@ namespace CompatGdi
LeaveCriticalSection(&g_gdiCriticalSection); LeaveCriticalSection(&g_gdiCriticalSection);
Compat::origProcs.AcquireDDThreadLock(); Compat::origProcs.AcquireDDThreadLock();
EnterCriticalSection(&g_gdiCriticalSection); EnterCriticalSection(&g_gdiCriticalSection);
if (!lockPrimarySurface()) if (!lockPrimarySurface(lockFlags))
{ {
Compat::origProcs.ReleaseDDThreadLock(); Compat::origProcs.ReleaseDDThreadLock();
return false; return false;

View File

@ -6,7 +6,7 @@
namespace CompatGdi namespace CompatGdi
{ {
bool beginGdiRendering(); bool beginGdiRendering(DWORD lockFlags = 0);
void endGdiRendering(); void endGdiRendering();
void disableEmulation(); void disableEmulation();

View File

@ -10,6 +10,9 @@ namespace
{ {
std::unordered_map<void*, const char*> g_funcNames; std::unordered_map<void*, const char*> g_funcNames;
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename... Params>
DWORD getDdLockFlags(Params... params);
BOOL WINAPI GdiDrawStream(HDC, DWORD, DWORD) { return FALSE; } BOOL WINAPI GdiDrawStream(HDC, DWORD, DWORD) { return FALSE; }
BOOL WINAPI PolyPatBlt(HDC, DWORD, DWORD, DWORD, DWORD) { return FALSE; } BOOL WINAPI PolyPatBlt(HDC, DWORD, DWORD, DWORD, DWORD) { return FALSE; }
@ -67,7 +70,8 @@ namespace
Compat::LogEnter(g_funcNames[origFunc], params...); Compat::LogEnter(g_funcNames[origFunc], params...);
#endif #endif
if (!hasDisplayDcArg(params...) || !CompatGdi::beginGdiRendering()) if (!hasDisplayDcArg(params...) ||
!CompatGdi::beginGdiRendering(getDdLockFlags<OrigFuncPtr, origFunc>(params...)))
{ {
Result result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(params...); Result result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(params...);
@ -107,6 +111,18 @@ namespace
return &compatGdiDcFunc<OrigFuncPtr, origFunc, Result, Params...>; return &compatGdiDcFunc<OrigFuncPtr, origFunc, Result, Params...>;
} }
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename... Params>
DWORD getDdLockFlags(Params...)
{
return 0;
}
template <>
DWORD getDdLockFlags<decltype(&GetPixel), &GetPixel>(HDC, int, int)
{
return DDLOCK_READONLY;
}
template <typename OrigFuncPtr, OrigFuncPtr origFunc> template <typename OrigFuncPtr, OrigFuncPtr origFunc>
void hookGdiDcFunction(const char* moduleName, const char* funcName) void hookGdiDcFunction(const char* moduleName, const char* funcName)
{ {