Wait for the asynchronous update thread to complete if the app
requests it. Fixed blit offseting issues in windowed mode.
This commit is contained in:
parent
5f1565e7fd
commit
1af798920c
|
@ -36,9 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
|
|||
/* if you use OWN_WINDOW, don't use SYNC_UPDATE, or you may get trouble */
|
||||
/* #define SYNC_UPDATE */
|
||||
/*
|
||||
* FIXME: This does not work any more because the created window has its own
|
||||
* FIXME: This does not work any more because the created window has its own
|
||||
* thread queue that cannot be manipulated by application threads.
|
||||
* #define OWN_WINDOW
|
||||
* #define OWN_WINDOW
|
||||
*/
|
||||
|
||||
#ifdef OWN_WINDOW
|
||||
|
@ -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);
|
||||
User_copy_to_screen(This, pRect);
|
||||
#else
|
||||
USER_PRIV_VAR(priv, This);
|
||||
SetEvent(priv->user.update_event);
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue