PATCH: some ddraw speedups

Marcus Meissner marcus at jet.franken.de
Sat Sep 8 12:29:53 CDT 2001


Hi,

This patch contains ddraw related stuff:

* Added dwFlags to lock_update()
  The USER mode does not to blt the old surface for DDLOCK_WRITEONLY.

* Restrict blting to the locked rectangle.

  The ddraw side now remembers the 'last locked' rectangle (if unlock gets
  passed a NULL rectangle) and only Blts this rectangle from and back to
  the screen.

  It also uses the clipping window to limit extents.

* The HAL driver now looks for Lock and Unlock and tries to use it, if 
  it is there. This required structure definitions for DDHAL_LOCKDATA and
  DDHAL_UNLOCKDATA.

  There is no HAL driver there yet to use this, but this part interlocked
  with parts above. (I am working towards implementing such a HAL driver.)

Ciao, Marcus

Changelog:
	Added dwFlags to lock_update private functions so we can pass
	WRITEONLY/READONLY.
	Added those flags to the internal Lock() calls.
	Only copy the surface from screen to surface if not writeonly.
	Restrict blitting between display window and surface to the 
	locked/unlocked rectangle and the clipwindow section.
	Added defines for DDHAL_UNLOCKDATA/DDHAL_LOCKDATA, added
	calls to HAL implementation.

Index: include/ddrawi.h
===================================================================
RCS file: /home/wine/wine/include/ddrawi.h,v
retrieving revision 1.3
diff -u -r1.3 ddrawi.h
--- include/ddrawi.h	2001/04/16 19:04:58	1.3
+++ include/ddrawi.h	2001/09/08 14:48:16
@@ -538,6 +538,24 @@
     LPDDRAWI_DDRAWSURFACE_LCL	lpSurfTargLeft;
 } DDHAL_FLIPDATA;
 
+typedef struct _DDHAL_LOCKDATA {
+    LPDDRAWI_DIRECTDRAW_GBL	lpDD;
+    LPDDRAWI_DDRAWSURFACE_LCL	lpDDSurface;
+    DWORD			bHasRect;
+    RECTL			rArea;
+    LPVOID			lpSurfData;
+    HRESULT			ddRVal;
+    LPDDHALSURFCB_LOCK		Lock;
+    DWORD			dwFlags;
+} DDHAL_LOCKDATA;
+
+typedef struct _DDHAL_UNLOCKDATA {
+    LPDDRAWI_DIRECTDRAW_GBL	lpDD;
+    LPDDRAWI_DDRAWSURFACE_LCL	lpDDSurface;
+    HRESULT			ddRVal;
+    LPDDHALSURFCB_UNLOCK	Unlock;
+} DDHAL_UNLOCKDATA;
+
 typedef struct _DDHAL_BLTDATA {
     LPDDRAWI_DIRECTDRAW_GBL	lpDD;
     LPDDRAWI_DDRAWSURFACE_LCL	lpDDDestSurface;
Index: dlls/ddraw/ddraw_private.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/ddraw_private.h,v
retrieving revision 1.20
diff -u -r1.20 ddraw_private.h
--- dlls/ddraw/ddraw_private.h	2001/07/28 00:09:07	1.20
+++ dlls/ddraw/ddraw_private.h	2001/09/08 14:48:26
@@ -222,6 +222,7 @@
     DDSURFACEDESC2 surface_desc;
 
     HDC hDC;
+    RECT lastlockrect;
     BOOL dc_in_use;
 
     HRESULT (*duplicate_surface)(IDirectDrawSurfaceImpl* src,
@@ -230,7 +231,7 @@
     HRESULT (*late_allocate)(IDirectDrawSurfaceImpl *This);
     BOOL (*attach)(IDirectDrawSurfaceImpl *This, IDirectDrawSurfaceImpl *to);
     BOOL (*detach)(IDirectDrawSurfaceImpl *This);
-    void (*lock_update)(IDirectDrawSurfaceImpl* This, LPCRECT pRect);
+    void (*lock_update)(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags);
     void (*unlock_update)(IDirectDrawSurfaceImpl* This, LPCRECT pRect);
     void (*lose_surface)(IDirectDrawSurfaceImpl* This);
     BOOL (*flip_data)(IDirectDrawSurfaceImpl* front,
Index: dlls/ddraw/dsurface/dib.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/dib.c,v
retrieving revision 1.4
diff -u -r1.4 dib.c
--- dlls/ddraw/dsurface/dib.c	2001/04/17 17:36:28	1.4
+++ dlls/ddraw/dsurface/dib.c	2001/09/08 14:48:28
@@ -322,9 +322,9 @@
     DD_STRUCT_INIT(&sdesc);
 
     sdesc.dwSize = sizeof(sdesc);
-    if (src) IDirectDrawSurface7_Lock(src, NULL, &sdesc, 0, 0);
+    if (src) IDirectDrawSurface7_Lock(src, NULL, &sdesc, DDLOCK_READONLY, 0);
     ddesc.dwSize = sizeof(ddesc);
-    IDirectDrawSurface7_Lock(iface,NULL,&ddesc,0,0);
+    IDirectDrawSurface7_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
 
     if (TRACE_ON(ddraw)) {
 	if (rdst) TRACE("\tdestrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
Index: dlls/ddraw/dsurface/hal.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/hal.c,v
retrieving revision 1.2
diff -u -r1.2 hal.c
--- dlls/ddraw/dsurface/hal.c	2001/04/18 17:40:43	1.2
+++ dlls/ddraw/dsurface/hal.c	2001/09/08 14:48:28
@@ -239,18 +254,50 @@
 }
 
 void HAL_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
-				       LPCRECT pRect)
+				       LPCRECT pRect, DWORD dwFlags)
 {
+    LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->more.lpDD_lcl->lpGbl;
+    DDHAL_LOCKDATA	data;
+
+    data.lpDD		= dd_gbl;
+    data.lpDDSurface	= &This->local;
+    data.ddRVal		= 0;
+    data.lpSurfData	= This->surface_desc.lpSurface; /* FIXME: correct? */
+    if (pRect) {
+	data.rArea.top	= pRect->top;
+	data.rArea.bottom	= pRect->bottom;
+	data.rArea.left	= pRect->left;
+	data.rArea.right	= pRect->right;
+	data.bHasRect 	= TRUE;
+    } else {
+	data.bHasRect 	= FALSE;
+    }
+    data.dwFlags	= dwFlags;
+
+    data.Lock		= dd_gbl->lpDDCBtmp->HALDDSurface.Lock;
+    if (data.Lock && (data.Lock(&data) == DDHAL_DRIVER_HANDLED))
+	return;
+
     if (HAL_IsUser(This)) {
-	User_DirectDrawSurface_lock_update(This, pRect);
+	User_DirectDrawSurface_lock_update(This, pRect, dwFlags);
     } else {
-	Main_DirectDrawSurface_lock_update(This, pRect);
+	Main_DirectDrawSurface_lock_update(This, pRect, dwFlags);
     }
 }
 
 void HAL_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
 					 LPCRECT pRect)
 {
+    LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->more.lpDD_lcl->lpGbl;
+    DDHAL_UNLOCKDATA	data;
+
+    data.lpDD		= dd_gbl;
+    data.lpDDSurface	= &This->local;
+    data.ddRVal		= 0;
+    data.Unlock		= dd_gbl->lpDDCBtmp->HALDDSurface.Unlock;
+    if (data.Unlock && (data.Unlock(&data) == DDHAL_DRIVER_HANDLED))
+	return;
+
     if (HAL_IsUser(This)) {
 	User_DirectDrawSurface_unlock_update(This, pRect);
     } else {
Index: dlls/ddraw/dsurface/hal.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/hal.h,v
retrieving revision 1.1
diff -u -r1.1 hal.h
--- dlls/ddraw/dsurface/hal.h	2001/04/17 17:48:19	1.1
+++ dlls/ddraw/dsurface/hal.h	2001/09/08 14:48:28
@@ -45,7 +45,7 @@
 HRESULT HAL_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
 						LPDIRECTDRAWSURFACE7* ppDup);
 void HAL_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
-				       LPCRECT pRect);
+				       LPCRECT pRect, DWORD dwFlags);
 void HAL_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
 					 LPCRECT pRect);
 BOOL HAL_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
Index: dlls/ddraw/dsurface/main.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/main.c,v
retrieving revision 1.22
diff -u -r1.22 main.c
--- dlls/ddraw/dsurface/main.c	2001/08/09 21:21:13	1.22
+++ dlls/ddraw/dsurface/main.c	2001/09/08 14:48:30
@@ -163,7 +163,8 @@
 }
 
 void
-Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
+Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect,
+	DWORD dwFlags)
 {
 }
 
@@ -680,7 +681,7 @@
      * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
      * thread has it locked, but GetDC does not. */
     ddsd.dwSize = sizeof(ddsd);
-    hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, 0, 0);
+    hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, DDLOCK_READONLY, 0);
     if (FAILED(hr))
     {
 	UNLOCK_OBJECT(This);
@@ -904,11 +905,13 @@
 	  return DDERR_INVALIDPARAMS;
        }
 
-	This->lock_update(This, prect);
+	This->lock_update(This, prect, flags);
        
 	pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
 	    + prect->top * This->surface_desc.u1.lPitch
 	    + prect->left * GET_BPP(This->surface_desc);
+    } else {
+	This->lock_update(This, NULL, flags);
     }
 
     return DD_OK;
Index: dlls/ddraw/dsurface/main.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/main.h,v
retrieving revision 1.3
diff -u -r1.3 main.h
--- dlls/ddraw/dsurface/main.h	2001/04/16 19:35:18	1.3
+++ dlls/ddraw/dsurface/main.h	2001/09/08 14:48:30
@@ -44,7 +44,7 @@
 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This);
 void
 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
-				   LPCRECT pRect);
+				   LPCRECT pRect, DWORD dwFlags);
 void
 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
 				     LPCRECT pRect);
Index: dlls/ddraw/dsurface/user.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/user.h,v
retrieving revision 1.3
diff -u -r1.3 user.h
--- dlls/ddraw/dsurface/user.h	2001/04/17 17:34:11	1.3
+++ dlls/ddraw/dsurface/user.h	2001/09/08 14:48:30
@@ -35,7 +35,7 @@
 void User_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This);
 
 void User_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
-					LPCRECT pRect);
+					LPCRECT pRect, DWORD dwFlags);
 void User_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
 					  LPCRECT pRect);
 void User_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
Index: dlls/ddraw/dsurface/thunks.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/thunks.c,v
retrieving revision 1.3
diff -u -r1.3 thunks.c
--- dlls/ddraw/dsurface/thunks.c	2001/04/16 19:06:13	1.3
+++ dlls/ddraw/dsurface/thunks.c	2001/09/08 15:11:25
@@ -300,8 +300,8 @@
 static HRESULT WINAPI
 IDirectDrawSurface3Impl_Unlock(LPDIRECTDRAWSURFACE3 This, LPVOID data)
 {
-    /* XXX This might be wrong as LPVOID changed to LPRECT along the way. */
-    return IDirectDrawSurface7_Unlock(CONVERT(This), data);
+    /* data might not be the LPRECT of later versions, so drop it. */
+    return IDirectDrawSurface7_Unlock(CONVERT(This), NULL);
 }
 
 static HRESULT WINAPI
Index: dlls/ddraw/dsurface/user.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/user.c,v
retrieving revision 1.6
diff -u -r1.6 user.c
--- dlls/ddraw/dsurface/user.c	2001/07/31 00:14:06	1.6
+++ dlls/ddraw/dsurface/user.c	2001/09/08 16:10:36
@@ -172,9 +172,16 @@
 }
 
 void User_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
-					LPCRECT pRect)
+					LPCRECT pRect, DWORD dwFlags)
 {
-    User_copy_from_screen(This, pRect);
+    if (!(dwFlags & DDLOCK_WRITEONLY))
+	User_copy_from_screen(This, pRect);
+
+    if (pRect) {
+	This->lastlockrect = *pRect;
+    } else {
+	This->lastlockrect.left = This->lastlockrect.right = 0;
+    }
 }
 
 void User_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
@@ -464,14 +471,13 @@
 
 static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc)
 {
-    /* rc is unused. We copy the whole thing. */
-
     if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
     {
 	POINT offset;
 	HWND hDisplayWnd;
 	HDC hDisplayDC;
 	HDC hSurfaceDC;
+	RECT drawrect;
 
 	if (FAILED(This->get_dc(This, &hSurfaceDC)))
 	    return;
@@ -488,28 +494,65 @@
 	    RealizePalette(hDisplayDC); /* sends messages => deadlocks */
 	}
 #endif
-
-	BitBlt(hDisplayDC, 0, 0, This->surface_desc.dwWidth,
-	       This->surface_desc.dwHeight, hSurfaceDC, offset.x, offset.y,
-	       SRCCOPY);
-
+	drawrect.left	= 0;
+	drawrect.right	= This->surface_desc.dwWidth;
+	drawrect.top	= 0;
+	drawrect.bottom	= This->surface_desc.dwHeight;
+
+	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);
+		IntersectRect(&drawrect,&drawrect,&xrc);
+		/* translate it back to its original position */
+		OffsetRect(&drawrect,-offset.x,-offset.y);
+	    }
+	}
+	if (rc)
+	    IntersectRect(&drawrect,&drawrect,rc);
+	else {
+	    /* Only use this if the caller did not pass a rectangle, since
+	     * due to double locking this could be the wrong one ... */
+	    if (This->lastlockrect.left != This->lastlockrect.right)
+		IntersectRect(&drawrect,&drawrect,&This->lastlockrect);
+	}
+	BitBlt(hDisplayDC,
+		drawrect.left+offset.x, drawrect.top+offset.y,
+		drawrect.right-drawrect.left, drawrect.bottom-drawrect.top,
+		hSurfaceDC,
+		drawrect.left, drawrect.top,
+		SRCCOPY
+	);
 	ReleaseDC(hDisplayWnd, hDisplayDC);
     }
 }
 
 static void User_copy_from_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc)
 {
-    /* rc is unused. We copy the whole thing. */
-
     if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
     {
 	POINT offset;
 	HWND hDisplayWnd = get_display_window(This, &offset);
 	HDC hDisplayDC = GetDC(hDisplayWnd);
-
-	BitBlt(This->hDC, offset.x, offset.y, This->surface_desc.dwWidth,
-	       This->surface_desc.dwHeight, hDisplayDC, 0, 0, SRCCOPY);
+	RECT drawrect;
 
+	drawrect.left	= 0;
+	drawrect.right	= This->surface_desc.dwWidth;
+	drawrect.top	= 0;
+	drawrect.bottom	= This->surface_desc.dwHeight;
+	if (rc)
+	    IntersectRect(&drawrect,&drawrect,rc);
+
+	BitBlt(This->hDC,
+	    drawrect.left, drawrect.top,
+	    drawrect.right-drawrect.left, drawrect.bottom-drawrect.top,
+	    hDisplayDC,
+	    drawrect.left+offset.x, drawrect.top+offset.y,
+	    SRCCOPY
+	);
 	ReleaseDC(hDisplayWnd, hDisplayDC);
     }
 }




More information about the wine-patches mailing list