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 */
|
/* 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,
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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
|
||||||
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)
|
||||||
#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)
|
||||||
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)
|
||||||
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
|
||||||
{
|
{
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue