Commit 1af79892 authored by Ove Kaaven's avatar Ove Kaaven Committed by Alexandre Julliard

Wait for the asynchronous update thread to complete if the app

requests it. Fixed blit offseting issues in windowed mode.
parent 5f1565e7
......@@ -96,12 +96,14 @@ User_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
DirectDrawSurface_RegisterClass();
#endif
#ifndef SYNC_UPDATE
InitializeCriticalSection(&priv->user.crit);
priv->user.refresh_event = CreateEventA(NULL, TRUE, FALSE, NULL);
priv->user.update_event = CreateEventA(NULL, FALSE, FALSE, NULL);
priv->user.update_thread = CreateThread(NULL, 0, User_update_thread, This, 0, NULL);
#ifdef OWN_WINDOW
if (This->ddraw_owner->cooperative_level & DDSCL_FULLSCREEN) {
/* wait for window creation (or update thread destruction) */
while (WaitForMultipleObjects(1, &priv->user.update_thread, FALSE, 10) == WAIT_TIMEOUT)
while (WaitForMultipleObjects(1, &priv->user.update_thread, FALSE, 100) == WAIT_TIMEOUT)
if (This->more.lpDDRAWReserved) break;
if (!This->more.lpDDRAWReserved) {
ERR("window creation failed\n");
......@@ -174,7 +176,10 @@ void User_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
WaitForSingleObject(priv->user.update_thread,INFINITE);
#endif
TRACE("update thread terminated\n");
CloseHandle(event);
CloseHandle(priv->user.update_thread);
CloseHandle(priv->user.refresh_event);
DeleteCriticalSection(&priv->user.crit);
#else
#ifdef OWN_WINDOW
User_destroy_own_window(This);
......@@ -189,11 +194,44 @@ void User_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
DIB_DirectDrawSurface_final_release(This);
}
static int User_DirectDrawSurface_init_wait(IDirectDrawSurfaceImpl* This)
{
USER_PRIV_VAR(priv, This);
int need_wait;
EnterCriticalSection(&priv->user.crit);
priv->user.wait_count++;
need_wait = priv->user.in_refresh;
LeaveCriticalSection(&priv->user.crit);
return need_wait;
}
static void User_DirectDrawSurface_end_wait(IDirectDrawSurfaceImpl* This)
{
USER_PRIV_VAR(priv, This);
EnterCriticalSection(&priv->user.crit);
if (!--priv->user.wait_count)
ResetEvent(priv->user.refresh_event);
LeaveCriticalSection(&priv->user.crit);
}
static void User_DirectDrawSurface_wait_update(IDirectDrawSurfaceImpl* This)
{
USER_PRIV_VAR(priv, This);
if (priv->user.in_refresh) {
if (User_DirectDrawSurface_init_wait(This))
WaitForSingleObject(priv->user.refresh_event, 2);
User_DirectDrawSurface_end_wait(This);
}
}
void User_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
LPCRECT pRect, DWORD dwFlags)
{
#if 0
if (!(dwFlags & DDLOCK_WRITEONLY))
User_copy_from_screen(This, pRect);
#endif
if (dwFlags & DDLOCK_WAIT) User_DirectDrawSurface_wait_update(This);
if (pRect) {
This->lastlockrect = *pRect;
......@@ -205,12 +243,15 @@ void User_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
void User_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
LPCRECT pRect)
{
if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
{
#ifdef SYNC_UPDATE
User_copy_to_screen(This, pRect);
#else
USER_PRIV_VAR(priv, This);
SetEvent(priv->user.update_event);
#endif
}
}
void User_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
......@@ -236,7 +277,9 @@ void User_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
DWORD dwStart, DWORD dwCount,
LPPALETTEENTRY palent)
{
#ifndef SYNC_UPDATE
USER_PRIV_VAR(priv, This);
#endif
DIB_DirectDrawSurface_update_palette(This, pal, dwStart, dwCount, palent);
/* FIXME: realize palette on display window */
......@@ -279,8 +322,9 @@ void User_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This, DWORD dwFl
User_copy_to_screen(This,NULL);
#else
USER_PRIV_VAR(priv, This);
This->lastlockrect.left = This->lastlockrect.right = 0;
assert(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE);
if (dwFlags & DDFLIP_WAIT) User_DirectDrawSurface_wait_update(This);
This->lastlockrect.left = This->lastlockrect.right = 0;
SetEvent(priv->user.update_event);
#endif
}
......@@ -473,14 +517,21 @@ static DWORD CALLBACK User_update_thread(LPVOID arg)
#endif
if (ret == WAIT_OBJECT_0)
{
if (*pActive)
if (*pActive) {
priv->user.in_refresh = TRUE;
User_copy_to_screen(This, NULL);
else
EnterCriticalSection(&priv->user.crit);
priv->user.in_refresh = FALSE;
if (priv->user.wait_count)
SetEvent(priv->user.refresh_event);
LeaveCriticalSection(&priv->user.crit);
} else
break;
}
else if (ret != WAIT_OBJECT_0+1) break;
} while (TRUE);
SetEvent(priv->user.refresh_event);
#ifdef OWN_WINDOW
User_destroy_own_window(This);
#endif
......@@ -522,13 +573,9 @@ static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc)
if (This->clipper) {
RECT xrc;
HWND hwnd = This->clipper->hWnd;
if (hwnd && GetWindowRect(hwnd,&xrc)) {
/* Do not forget to honor the offset within the clip window. */
/* translate the surface to 0.0 of the clip window */
OffsetRect(&drawrect,offset.x,offset.y);
if (hwnd && GetClientRect(hwnd,&xrc)) {
OffsetRect(&xrc,offset.x,offset.y);
IntersectRect(&drawrect,&drawrect,&xrc);
/* translate it back to its original position */
OffsetRect(&drawrect,-offset.x,-offset.y);
}
}
if (rc)
......@@ -540,7 +587,7 @@ static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc)
IntersectRect(&drawrect,&drawrect,&This->lastlockrect);
}
BitBlt(hDisplayDC,
drawrect.left+offset.x, drawrect.top+offset.y,
drawrect.left-offset.x, drawrect.top-offset.y,
drawrect.right-drawrect.left, drawrect.bottom-drawrect.top,
hSurfaceDC,
drawrect.left, drawrect.top,
......
......@@ -28,7 +28,9 @@ struct User_DirectDrawSurfaceImpl_Part
{
HWND window;
HDC cached_dc;
HANDLE update_thread, update_event;
HANDLE update_thread, update_event, refresh_event;
volatile int wait_count, in_refresh;
CRITICAL_SECTION crit;
};
typedef struct
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment