mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Fixed synchronization issue in beginGdiRendering
It's not sufficient to make g_renderingRefCount atomic, because after it is found to be nonzero in beginGdiRendering, a call to endGdiRendering from another thread may make it zero before beginGdiRendering has a chance of entering the critical section. This would mean that the DirectDraw primary surface is no longer locked, even though beginGdiRendering expects that it is. To prevent potential issues, the g_renderingRefCount check is now also guarded by the critical section.
This commit is contained in:
parent
cc5a4c7cef
commit
74f306b5b0
@ -1,5 +1,3 @@
|
||||
#include <atomic>
|
||||
|
||||
#include "CompatDirectDrawPalette.h"
|
||||
#include "CompatDirectDrawSurface.h"
|
||||
#include "CompatGdi.h"
|
||||
@ -17,7 +15,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
std::atomic<DWORD> g_renderingRefCount = 0;
|
||||
DWORD g_renderingRefCount = 0;
|
||||
DWORD g_ddLockThreadRenderingRefCount = 0;
|
||||
DWORD g_ddLockThreadId = 0;
|
||||
HANDLE g_ddUnlockBeginEvent = nullptr;
|
||||
@ -93,21 +91,19 @@ namespace CompatGdi
|
||||
return false;
|
||||
}
|
||||
|
||||
Compat::ScopedCriticalSection gdiLock(g_gdiCriticalSection);
|
||||
|
||||
if (0 == g_renderingRefCount)
|
||||
{
|
||||
LeaveCriticalSection(&g_gdiCriticalSection);
|
||||
Compat::origProcs.AcquireDDThreadLock();
|
||||
EnterCriticalSection(&g_gdiCriticalSection);
|
||||
if (!lockPrimarySurface())
|
||||
{
|
||||
LeaveCriticalSection(&g_gdiCriticalSection);
|
||||
Compat::origProcs.ReleaseDDThreadLock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnterCriticalSection(&g_gdiCriticalSection);
|
||||
}
|
||||
|
||||
if (GetCurrentThreadId() == g_ddLockThreadId)
|
||||
{
|
||||
@ -115,13 +111,12 @@ namespace CompatGdi
|
||||
}
|
||||
|
||||
++g_renderingRefCount;
|
||||
LeaveCriticalSection(&g_gdiCriticalSection);
|
||||
return true;
|
||||
}
|
||||
|
||||
void endGdiRendering()
|
||||
{
|
||||
Compat::ScopedCriticalSection gdiLock(CompatGdi::g_gdiCriticalSection);
|
||||
Compat::ScopedCriticalSection gdiLock(g_gdiCriticalSection);
|
||||
|
||||
if (GetCurrentThreadId() == g_ddLockThreadId)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user