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
...@@ -36,9 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(ddraw); ...@@ -36,9 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
/* if you use OWN_WINDOW, don't use SYNC_UPDATE, or you may get trouble */ /* if you use OWN_WINDOW, don't use SYNC_UPDATE, or you may get trouble */
/* #define SYNC_UPDATE */ /* #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. * thread queue that cannot be manipulated by application threads.
* #define OWN_WINDOW * #define OWN_WINDOW
*/ */
#ifdef OWN_WINDOW #ifdef OWN_WINDOW
...@@ -96,12 +96,14 @@ User_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This, ...@@ -96,12 +96,14 @@ User_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
DirectDrawSurface_RegisterClass(); DirectDrawSurface_RegisterClass();
#endif #endif
#ifndef SYNC_UPDATE #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_event = CreateEventA(NULL, FALSE, FALSE, NULL);
priv->user.update_thread = CreateThread(NULL, 0, User_update_thread, This, 0, NULL); priv->user.update_thread = CreateThread(NULL, 0, User_update_thread, This, 0, NULL);
#ifdef OWN_WINDOW #ifdef OWN_WINDOW
if (This->ddraw_owner->cooperative_level & DDSCL_FULLSCREEN) { if (This->ddraw_owner->cooperative_level & DDSCL_FULLSCREEN) {
/* wait for window creation (or update thread destruction) */ /* 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) break;
if (!This->more.lpDDRAWReserved) { if (!This->more.lpDDRAWReserved) {
ERR("window creation failed\n"); ERR("window creation failed\n");
...@@ -174,7 +176,10 @@ void User_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This) ...@@ -174,7 +176,10 @@ void User_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
WaitForSingleObject(priv->user.update_thread,INFINITE); WaitForSingleObject(priv->user.update_thread,INFINITE);
#endif #endif
TRACE("update thread terminated\n"); TRACE("update thread terminated\n");
CloseHandle(event);
CloseHandle(priv->user.update_thread); CloseHandle(priv->user.update_thread);
CloseHandle(priv->user.refresh_event);
DeleteCriticalSection(&priv->user.crit);
#else #else
#ifdef OWN_WINDOW #ifdef OWN_WINDOW
User_destroy_own_window(This); User_destroy_own_window(This);
...@@ -189,11 +194,44 @@ void User_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This) ...@@ -189,11 +194,44 @@ void User_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
DIB_DirectDrawSurface_final_release(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, void User_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
LPCRECT pRect, DWORD dwFlags) LPCRECT pRect, DWORD dwFlags)
{ {
#if 0
if (!(dwFlags & DDLOCK_WRITEONLY)) if (!(dwFlags & DDLOCK_WRITEONLY))
User_copy_from_screen(This, pRect); User_copy_from_screen(This, pRect);
#endif
if (dwFlags & DDLOCK_WAIT) User_DirectDrawSurface_wait_update(This);
if (pRect) { if (pRect) {
This->lastlockrect = *pRect; This->lastlockrect = *pRect;
...@@ -205,12 +243,15 @@ void User_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, ...@@ -205,12 +243,15 @@ void User_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
void User_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This, void User_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
LPCRECT pRect) LPCRECT pRect)
{ {
if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
{
#ifdef SYNC_UPDATE #ifdef SYNC_UPDATE
User_copy_to_screen(This, pRect); User_copy_to_screen(This, pRect);
#else #else
USER_PRIV_VAR(priv, This); USER_PRIV_VAR(priv, This);
SetEvent(priv->user.update_event); SetEvent(priv->user.update_event);
#endif #endif
}
} }
void User_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This, void User_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
...@@ -236,7 +277,9 @@ void User_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This, ...@@ -236,7 +277,9 @@ void User_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
DWORD dwStart, DWORD dwCount, DWORD dwStart, DWORD dwCount,
LPPALETTEENTRY palent) LPPALETTEENTRY palent)
{ {
#ifndef SYNC_UPDATE
USER_PRIV_VAR(priv, This); USER_PRIV_VAR(priv, This);
#endif
DIB_DirectDrawSurface_update_palette(This, pal, dwStart, dwCount, palent); DIB_DirectDrawSurface_update_palette(This, pal, dwStart, dwCount, palent);
/* FIXME: realize palette on display window */ /* FIXME: realize palette on display window */
...@@ -279,8 +322,9 @@ void User_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This, DWORD dwFl ...@@ -279,8 +322,9 @@ void User_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This, DWORD dwFl
User_copy_to_screen(This,NULL); User_copy_to_screen(This,NULL);
#else #else
USER_PRIV_VAR(priv, This); USER_PRIV_VAR(priv, This);
This->lastlockrect.left = This->lastlockrect.right = 0;
assert(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE); 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); SetEvent(priv->user.update_event);
#endif #endif
} }
...@@ -473,14 +517,21 @@ static DWORD CALLBACK User_update_thread(LPVOID arg) ...@@ -473,14 +517,21 @@ static DWORD CALLBACK User_update_thread(LPVOID arg)
#endif #endif
if (ret == WAIT_OBJECT_0) if (ret == WAIT_OBJECT_0)
{ {
if (*pActive) if (*pActive) {
priv->user.in_refresh = TRUE;
User_copy_to_screen(This, NULL); 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; break;
} }
else if (ret != WAIT_OBJECT_0+1) break; else if (ret != WAIT_OBJECT_0+1) break;
} while (TRUE); } while (TRUE);
SetEvent(priv->user.refresh_event);
#ifdef OWN_WINDOW #ifdef OWN_WINDOW
User_destroy_own_window(This); User_destroy_own_window(This);
#endif #endif
...@@ -522,13 +573,9 @@ static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc) ...@@ -522,13 +573,9 @@ static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc)
if (This->clipper) { if (This->clipper) {
RECT xrc; RECT xrc;
HWND hwnd = This->clipper->hWnd; HWND hwnd = This->clipper->hWnd;
if (hwnd && GetWindowRect(hwnd,&xrc)) { if (hwnd && GetClientRect(hwnd,&xrc)) {
/* Do not forget to honor the offset within the clip window. */ OffsetRect(&xrc,offset.x,offset.y);
/* translate the surface to 0.0 of the clip window */
OffsetRect(&drawrect,offset.x,offset.y);
IntersectRect(&drawrect,&drawrect,&xrc); IntersectRect(&drawrect,&drawrect,&xrc);
/* translate it back to its original position */
OffsetRect(&drawrect,-offset.x,-offset.y);
} }
} }
if (rc) if (rc)
...@@ -540,7 +587,7 @@ static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc) ...@@ -540,7 +587,7 @@ static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc)
IntersectRect(&drawrect,&drawrect,&This->lastlockrect); IntersectRect(&drawrect,&drawrect,&This->lastlockrect);
} }
BitBlt(hDisplayDC, 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, drawrect.right-drawrect.left, drawrect.bottom-drawrect.top,
hSurfaceDC, hSurfaceDC,
drawrect.left, drawrect.top, drawrect.left, drawrect.top,
......
...@@ -28,7 +28,9 @@ struct User_DirectDrawSurfaceImpl_Part ...@@ -28,7 +28,9 @@ struct User_DirectDrawSurfaceImpl_Part
{ {
HWND window; HWND window;
HDC cached_dc; 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 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