And this... I think this improved diablo 2 performance. Not sure if it applies unedited. Log: Ove Kaaven <ovek@transgaming.com> Wait for the asynchronous update thread to complete if the app requests it. Fixed blit offseting issues in windowed mode. Index: wine/dlls/ddraw/dsurface/user.c diff -u wine/dlls/ddraw/dsurface/user.c:1.1.1.8 wine/dlls/ddraw/dsurface/user.c:1.57 --- wine/dlls/ddraw/dsurface/user.c:1.1.1.8 Sun Oct 28 06:13:59 2001 +++ wine/dlls/ddraw/dsurface/user.c Fri Feb 8 20:56:43 2002 @@ -72,14 +74,16 @@ 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) - if (This->more.lpDDRAWReserved) break; - if (!This->more.lpDDRAWReserved) { + 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"); } } @@ -95,8 +103,8 @@ User_create_own_window(This); #endif #endif - if (!This->more.lpDDRAWReserved) - This->more.lpDDRAWReserved = (LPVOID)pDD->window; + if (!This->more.lpDDRAWReserved) + This->more.lpDDRAWReserved = (LPVOID)pDD->window; } return DIB_DirectDrawSurface_alloc_dc(This, &priv->user.cached_dc); @@ -156,13 +164,16 @@ 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); #endif #endif - This->more.lpDDRAWReserved = 0; + This->more.lpDDRAWReserved = 0; #ifdef OWN_WINDOW DirectDrawSurface_UnregisterClass(); #endif @@ -171,11 +182,44 @@ 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; @@ -187,12 +231,15 @@ 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, @@ -218,7 +265,9 @@ 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 */ @@ -261,8 +310,9 @@ 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 } @@ -393,7 +443,7 @@ This->surface_desc.dwHeight, GetDesktopWindow(), 0, 0, This); - This->more.lpDDRAWReserved = (LPVOID)priv->user.window; + This->more.lpDDRAWReserved = (LPVOID)priv->user.window; SetWindowPos(priv->user.window, HWND_TOP, 0, 0, 0, 0, SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE| SWP_NOREDRAW|SWP_NOSENDCHANGING|SWP_NOSIZE|SWP_SHOWWINDOW); @@ -410,7 +460,7 @@ SetWindowPos(priv->user.window, 0, 0, 0, 0, 0, SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER| SWP_NOREDRAW|SWP_NOSENDCHANGING|SWP_NOSIZE|SWP_HIDEWINDOW); - This->more.lpDDRAWReserved = NULL; + This->more.lpDDRAWReserved = NULL; DestroyWindow(priv->user.window); priv->user.window = 0; } @@ -455,14 +505,21 @@ #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 @@ -504,13 +561,9 @@ 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) @@ -522,7 +575,7 @@ 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, Index: wine/dlls/ddraw/dsurface/user.h diff -u wine/dlls/ddraw/dsurface/user.h:1.1.1.4 wine/dlls/ddraw/dsurface/user.h:1.16 --- wine/dlls/ddraw/dsurface/user.h:1.1.1.4 Thu Oct 4 06:43:01 2001 +++ wine/dlls/ddraw/dsurface/user.h Sat May 5 12:36:54 2001 @@ -12,7 +12,9 @@ { 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