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 "CompatDirectDrawPalette.h"
|
||||||
#include "CompatDirectDrawSurface.h"
|
#include "CompatDirectDrawSurface.h"
|
||||||
#include "CompatGdi.h"
|
#include "CompatGdi.h"
|
||||||
@ -17,7 +15,7 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::atomic<DWORD> g_renderingRefCount = 0;
|
DWORD g_renderingRefCount = 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;
|
||||||
@ -93,21 +91,19 @@ namespace CompatGdi
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Compat::ScopedCriticalSection gdiLock(g_gdiCriticalSection);
|
||||||
|
|
||||||
if (0 == g_renderingRefCount)
|
if (0 == g_renderingRefCount)
|
||||||
{
|
{
|
||||||
|
LeaveCriticalSection(&g_gdiCriticalSection);
|
||||||
Compat::origProcs.AcquireDDThreadLock();
|
Compat::origProcs.AcquireDDThreadLock();
|
||||||
EnterCriticalSection(&g_gdiCriticalSection);
|
EnterCriticalSection(&g_gdiCriticalSection);
|
||||||
if (!lockPrimarySurface())
|
if (!lockPrimarySurface())
|
||||||
{
|
{
|
||||||
LeaveCriticalSection(&g_gdiCriticalSection);
|
|
||||||
Compat::origProcs.ReleaseDDThreadLock();
|
Compat::origProcs.ReleaseDDThreadLock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
EnterCriticalSection(&g_gdiCriticalSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetCurrentThreadId() == g_ddLockThreadId)
|
if (GetCurrentThreadId() == g_ddLockThreadId)
|
||||||
{
|
{
|
||||||
@ -115,13 +111,12 @@ namespace CompatGdi
|
|||||||
}
|
}
|
||||||
|
|
||||||
++g_renderingRefCount;
|
++g_renderingRefCount;
|
||||||
LeaveCriticalSection(&g_gdiCriticalSection);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void endGdiRendering()
|
void endGdiRendering()
|
||||||
{
|
{
|
||||||
Compat::ScopedCriticalSection gdiLock(CompatGdi::g_gdiCriticalSection);
|
Compat::ScopedCriticalSection gdiLock(g_gdiCriticalSection);
|
||||||
|
|
||||||
if (GetCurrentThreadId() == g_ddLockThreadId)
|
if (GetCurrentThreadId() == g_ddLockThreadId)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user