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

View File

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

View File

@ -10,6 +10,9 @@ namespace
{
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 PolyPatBlt(HDC, DWORD, DWORD, DWORD, DWORD) { return FALSE; }
@ -67,7 +70,8 @@ namespace
Compat::LogEnter(g_funcNames[origFunc], params...);
#endif
if (!hasDisplayDcArg(params...) || !CompatGdi::beginGdiRendering())
if (!hasDisplayDcArg(params...) ||
!CompatGdi::beginGdiRendering(getDdLockFlags<OrigFuncPtr, origFunc>(params...)))
{
Result result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(params...);
@ -107,6 +111,18 @@ namespace
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>
void hookGdiDcFunction(const char* moduleName, const char* funcName)
{