[D3D] Use locking rectangles to optimize FB locks

Lionel Ulmer lionel.ulmer at free.fr
Tue Jun 3 16:52:15 CDT 2003


With this patch, DungeonSiege got a nice speed boost, it's now actually
playable even on my lowly box.

Some other games could benefit also from this if they do 'proper' surface
locking (ie they lock only the rectangle they want to change and not
everything like many do).

      Lionel (who will probably not send any other patches for the rest of
              the week :-) )

Changelog:
 - fix the texture upload code when RECT is actually used
 - optimize FB Locks / Unlocks when RECTs are used
  
-- 
		 Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
--- dlls/ddraw_CVS/d3ddevice/mesa.c	Tue Jun  3 18:50:16 2003
+++ dlls/ddraw/d3ddevice/mesa.c	Tue Jun  3 23:43:26 2003
@@ -107,11 +107,11 @@
 
     TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
     ENTER_GL();
-    if (gl_d3d_dev->state == SURFACE_MEMORY_DIRTY) {
-        d3d_dev->flush_to_framebuffer(d3d_dev, NULL, gl_d3d_dev->lock_surf);
+    if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
+        d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_BACK]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK]);
     }
-    gl_d3d_dev->state = SURFACE_GL;
-    gl_d3d_dev->front_state = SURFACE_GL;
+    gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
+    gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
     glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
     LEAVE_GL();
     
@@ -1076,11 +1076,11 @@
     EnterCriticalSection(&(This->crit));   
     
     ENTER_GL();
-    if (glThis->state == SURFACE_MEMORY_DIRTY) {
-        This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
+    if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
+        This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
     }
 
-    glThis->state = SURFACE_GL;
+    glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
     
     /* Just a hack for now.. Will have to find better algorithm :-/ */
     if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
@@ -2386,11 +2386,11 @@
     /* Clears the screen */
     ENTER_GL();
 
-    if (glThis->state == SURFACE_MEMORY_DIRTY) {
+    if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
         /* TODO: optimize here the case where Clear changes all the screen... */
-        This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
+        This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
     }
-    glThis->state = SURFACE_GL;
+    glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
 
     if (dwFlags & D3DCLEAR_ZBUFFER) {
 	bitfield |= GL_DEPTH_BUFFER_BIT;
@@ -2741,40 +2741,78 @@
 {
     IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
     IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
-    BOOLEAN is_front;
+    WINE_GL_BUFFER_TYPE buffer_type;
+    RECT loc_rect;
     
     if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
-        is_front = TRUE;
-	if ((gl_d3d_dev->front_state != SURFACE_GL) &&
-	    (gl_d3d_dev->front_lock_surf != This)) {
+        buffer_type = WINE_GL_BUFFER_FRONT;
+	if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
+	    (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
 	    ERR("Change of front buffer.. Expect graphic corruptions !\n");
 	}
-	gl_d3d_dev->front_lock_surf = This;
+	gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
     } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
-        is_front = FALSE;
-	if ((gl_d3d_dev->state != SURFACE_GL) &&
-	    (gl_d3d_dev->lock_surf != This)) {
+        buffer_type = WINE_GL_BUFFER_BACK;
+	if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
+	    (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
 	    ERR("Change of back buffer.. Expect graphic corruptions !\n");
 	}
-	gl_d3d_dev->lock_surf = This;
+	gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
     } else {
         ERR("Wrong surface type for locking !\n");
 	return;
     }
 
+    if (pRect == NULL) {
+	loc_rect.top = 0;
+	loc_rect.left = 0;
+	loc_rect.bottom = This->surface_desc.dwHeight;
+	loc_rect.right = This->surface_desc.dwWidth;
+	pRect = &loc_rect;
+    }
+    
     /* Try to acquire the device critical section */
     EnterCriticalSection(&(d3d_dev->crit));
     
-    if (((is_front == TRUE)  && (gl_d3d_dev->front_state == SURFACE_GL)) ||
-	((is_front == FALSE) && (gl_d3d_dev->state       == SURFACE_GL))) {
+    if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
+	ERR("Two consecutive locks on %s buffer... Expect problems !\n",
+	    (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
+    }
+    gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
+    
+    if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
+	/* Check if the new rectangle is in the previous one or not.
+	   If it is not, flush first the previous locks on screen.
+	*/
+	if ((pRect->top    < gl_d3d_dev->lock_rect[buffer_type].top) ||
+	    (pRect->left   < gl_d3d_dev->lock_rect[buffer_type].left) ||
+	    (pRect->right  > gl_d3d_dev->lock_rect[buffer_type].right) ||
+	    (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
+	    if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
+		TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
+		      (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
+		      pRect->left, pRect->top, pRect->right, pRect->bottom,
+		      gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
+		      gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
+		d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
+	    }
+	    gl_d3d_dev->state[buffer_type] = SURFACE_GL;
+	    gl_d3d_dev->lock_rect[buffer_type] = *pRect;
+	}
+	/* In the other case, do not upgrade the locking rectangle as it's no need... */
+    } else {
+	gl_d3d_dev->lock_rect[buffer_type] = *pRect;
+    }
+    
+    if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
         /* If the surface is already in memory, no need to do anything here... */
-        GLenum buffer_type;
+        GLenum buffer_format;
 	GLenum buffer_color;
-	RECT loc_rect;
 	int y;
 	char *dst;
 
-	TRACE(" copying frame buffer to main memory.\n");
+	TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
+	      pRect->left, pRect->top, pRect->right, pRect->bottom);
 	
 	/* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
 	   may only write to the device... But when we will blit it back to the screen, we need
@@ -2787,19 +2825,19 @@
 		(This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
 		(This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
 		(This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
-		buffer_type = GL_UNSIGNED_SHORT_5_6_5;
+		buffer_format = GL_UNSIGNED_SHORT_5_6_5;
 		buffer_color = GL_RGB;
 	    } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
 		       (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
 		       (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
 		       (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
-		buffer_type = GL_UNSIGNED_BYTE;
+		buffer_format = GL_UNSIGNED_BYTE;
 		buffer_color = GL_RGB;
 	    } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
 		       (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
 		       (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
 		       (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
-		buffer_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+		buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
 		buffer_color = GL_BGRA;
 	    } else {
 		ERR(" unsupported pixel format at device locking.\n");
@@ -2812,39 +2850,25 @@
 
 	ENTER_GL();
 	
-	if (is_front == TRUE)
+	if (buffer_type == WINE_GL_BUFFER_FRONT)
 	    /* Application wants to lock the front buffer */
 	    glReadBuffer(GL_FRONT);
 	else 
 	    /* Application wants to lock the back buffer */
 	    glReadBuffer(GL_BACK);
 
-	/* Just a hack while waiting for proper rectangle support */
-	pRect = NULL;
-	if (pRect == NULL) {
-	    loc_rect.top = 0;
-	    loc_rect.left = 0;
-	    loc_rect.bottom = This->surface_desc.dwHeight;
-	    loc_rect.right = This->surface_desc.dwWidth;
-	} else {
-	    loc_rect = *pRect;
-	}
-	
 	dst = ((char *)This->surface_desc.lpSurface) +
-	  (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
-	for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
-	     y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
+	  (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
+	for (y = (This->surface_desc.dwHeight - pRect->top - 1);
+	     y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
 	     y--) {
-	    glReadPixels(loc_rect.left, y,
-			 loc_rect.right - loc_rect.left, 1,
-			 buffer_color, buffer_type, dst);
+	    glReadPixels(pRect->left, y,
+			 pRect->right - pRect->left, 1,
+			 buffer_color, buffer_format, dst);
 	    dst += This->surface_desc.u1.lPitch;
 	}
 
-	if (is_front)
-	    gl_d3d_dev->front_state = SURFACE_MEMORY;
-	else
-	    gl_d3d_dev->state = SURFACE_MEMORY;
+	gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
 	
 #if 0
 	/* I keep this code here as it's very useful to debug :-) */
@@ -2876,13 +2900,16 @@
 
     /* Note : no need here to lock the 'device critical section' as we are already protected by
        the GL critical section. */
-    
-    loc_rect.top = 0;
-    loc_rect.left = 0;
-    loc_rect.bottom = surf->surface_desc.dwHeight;
-    loc_rect.right = surf->surface_desc.dwWidth;
 
-    TRACE(" flushing memory back to the frame-buffer (%ld,%ld) x (%ld,%ld).\n", loc_rect.top, loc_rect.left, loc_rect.right, loc_rect.bottom);
+    if (pRect == NULL) {
+	loc_rect.top = 0;
+	loc_rect.left = 0;
+	loc_rect.bottom = surf->surface_desc.dwHeight;
+	loc_rect.right = surf->surface_desc.dwWidth;
+	pRect = &loc_rect;
+    }
+    
+    TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
 
     /* This is a hack to prevent querying the current texture from GL */
     gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
@@ -2924,8 +2951,8 @@
     glEnable(GL_SCISSOR_TEST); 
     glDepthRange(0.0, 1.0);
     glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
-    glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
-	      loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
+    glScissor(pRect->left, surf->surface_desc.dwHeight - pRect->bottom,
+	      pRect->right - pRect->left, pRect->bottom - pRect->top);
     glDisable(GL_LIGHTING);
     glDisable(GL_CULL_FACE);
     glDisable(GL_ALPHA_TEST);
@@ -2934,15 +2961,15 @@
     glDisable(GL_FOG);
     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
     
-    for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
-        for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
+    for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
+        for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
 	    /* First, upload the texture... */
 	    RECT flush_rect;
 
 	    flush_rect.left = x;
 	    flush_rect.top = y;
-	    flush_rect.right  = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth)  ? surf->surface_desc.dwWidth  : (x + UNLOCK_TEX_SIZE);
-	    flush_rect.bottom = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? surf->surface_desc.dwHeight : (y + UNLOCK_TEX_SIZE);
+	    flush_rect.right  = (x + UNLOCK_TEX_SIZE > pRect->right)  ? pRect->right  : (x + UNLOCK_TEX_SIZE);
+	    flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
 
 	    upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
 
@@ -2997,21 +3024,28 @@
 
 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
 {
-    BOOLEAN is_front;
+    WINE_GL_BUFFER_TYPE buffer_type;
     IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
     IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
   
     if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
-        is_front = TRUE;
+        buffer_type = WINE_GL_BUFFER_FRONT;
     } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
-        is_front = FALSE;
+	buffer_type = WINE_GL_BUFFER_BACK;
     } else {
         ERR("Wrong surface type for locking !\n");
 	return;
     }
+
+    if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
+	ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
+	    (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
+    }
+    gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
+    
     /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
     if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
-        if (is_front == TRUE) {
+        if (buffer_type == WINE_GL_BUFFER_FRONT) {
 	    GLenum prev_draw;
 
 	    TRACE(" flushing front buffer immediatly on screen.\n");
@@ -3019,11 +3053,15 @@
 	    ENTER_GL();
 	    glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
 	    glDrawBuffer(GL_FRONT);
-	    d3d_dev->flush_to_framebuffer(d3d_dev, pRect, gl_d3d_dev->front_lock_surf);
+	    /* Note: we do not use the application provided lock rectangle but our own stored at
+	             lock time. This is because in old D3D versions, the 'lock' parameter did not
+		     exist.
+	    */
+	    d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_FRONT]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT]);
 	    glDrawBuffer(prev_draw);
 	    LEAVE_GL();
 	} else {
-	    gl_d3d_dev->state = SURFACE_MEMORY_DIRTY;
+	    gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
 	}
     }
 
@@ -3195,7 +3233,8 @@
     /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
     LEAVE_GL();
 
-    gl_object->state = SURFACE_GL;
+    gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
+    gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
     
     /* fill_device_capabilities(d3d->ddraw); */    
     
--- dlls/ddraw_CVS/mesa.c	Tue Jun  3 15:24:23 2003
+++ dlls/ddraw/mesa.c	Tue Jun  3 20:57:56 2003
@@ -608,7 +608,8 @@
     BOOL colorkey_active = need_alpha_ck && (surf_ptr->surface_desc.dwFlags & DDSD_CKSRCBLT);
     GLenum internal_format = GL_LUMINANCE; /* A bogus value to be sure to have a nice Mesa warning :-) */
     BYTE bpp = GET_BPP(surf_ptr->surface_desc);
-
+    BOOL sub_texture = TRUE;
+    
     current_surface = surf_ptr;
     current_level = level;
 
@@ -618,14 +619,9 @@
     }
 
     /* Note: we only check width here as you cannot have width non-zero while height is set to zero */
-    if (tex_width != 0) {
-	glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
-    } else {
-	if (surf_ptr->surface_desc.u1.lPitch == (surf_ptr->surface_desc.dwWidth * bpp)) {
-	    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-	} else {
-	    glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
-	}
+    if (tex_width == 0) {
+	sub_texture = FALSE;
+	
 	tex_width = surf_ptr->surface_desc.dwWidth;
 	tex_height = surf_ptr->surface_desc.dwHeight;
     }
@@ -853,6 +849,17 @@
 	}
     }
 
+    if ((sub_texture == TRUE) && (convert_type == NO_CONVERSION)) {
+	glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
+    } else {
+	if (surf_ptr->surface_desc.u1.lPitch == (surf_ptr->surface_desc.dwWidth * bpp)) {
+	    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+	} else {
+	    glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
+	}
+	
+    }
+    
     return DD_OK;
 }
 
@@ -863,7 +870,8 @@
     RECT lrect;
     DWORD width, height;
     BYTE bpp = GET_BPP(current_surface->surface_desc);
-
+    int line_increase;
+    
     if (rect == NULL) {
 	lrect.top = 0;
 	lrect.left = 0;
@@ -875,11 +883,15 @@
     width = rect->right - rect->left;
     height = rect->bottom - rect->top;
 
+    /* Used when converting stuff */
+    line_increase = src_d->dwWidth - width;
+    
     switch (convert_type) {
         case CONVERT_PALETTED: {
 	    IDirectDrawPaletteImpl* pal = current_surface->palette;
 	    BYTE table[256][4];
 	    int i;
+	    int x, y;
 	    BYTE *src = (BYTE *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
 	    
 	    if (pal == NULL) {
@@ -908,13 +920,16 @@
 		*temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
 					 current_tex_width * current_tex_height * sizeof(DWORD));
 	    dst = (BYTE *) *temp_buffer;
-	    
-	    for (i = 0; i < height * width; i++) {
-		BYTE color = *src++;
-		*dst++ = table[color][0];
-		*dst++ = table[color][1];
-		*dst++ = table[color][2];
-		*dst++ = table[color][3];
+
+	    for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+		    BYTE color = *src++;
+		    *dst++ = table[color][0];
+		    *dst++ = table[color][1];
+		    *dst++ = table[color][2];
+		    *dst++ = table[color][3];
+		}
+		src += line_increase;
 	    }
 	} break;
 
@@ -929,7 +944,7 @@
 	       Note2: when using color-keying + alpha, are the alpha bits part of the
 	              color-space or not ?
 	    */
-	    DWORD i;
+	    int x, y;
 	    WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
 	    
 	    if (*temp_buffer == NULL)
@@ -937,19 +952,22 @@
 					 current_tex_width * current_tex_height * sizeof(WORD));
 	    dst = (WORD *) *temp_buffer;
 	    
-	    for (i = 0; i < height * width; i++) {
-		WORD color = *src++;
-		*dst = ((color & 0xFFC0) | ((color & 0x1F) << 1));
-		if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-		    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-		    *dst |= 0x0001;
-		dst++;
+	    for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+		    WORD color = *src++;
+		    *dst = ((color & 0xFFC0) | ((color & 0x1F) << 1));
+		    if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			*dst |= 0x0001;
+		    dst++;
+		}
+		src += line_increase;
 	    }
 	} break;
 	
         case CONVERT_CK_5551: {
 	    /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
-	    DWORD i;
+	    int x, y;
 	    WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
 	    
 	    if (*temp_buffer == NULL)
@@ -957,19 +975,22 @@
 					 current_tex_width * current_tex_height * sizeof(WORD));
 	    dst = (WORD *) *temp_buffer;
 	    
-	    for (i = 0; i < height * width; i++) {
-		WORD color = *src++;
-		*dst = color & 0xFFFE;
-		if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-		    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-		    *dst |= color & 0x0001;
-		dst++;
+	    for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+		    WORD color = *src++;
+		    *dst = color & 0xFFFE;
+		    if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			*dst |= color & 0x0001;
+		    dst++;
+		}
+		src += line_increase;
 	    }
 	} break;
 	
         case CONVERT_CK_4444: {
 	    /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
-	    DWORD i;
+	    int x, y;
 	    WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
 	    
 	    if (*temp_buffer == NULL)
@@ -977,19 +998,22 @@
 					 current_tex_width * current_tex_height * sizeof(WORD));
 	    dst = (WORD *) *temp_buffer;
 	    
-	    for (i = 0; i < height * width; i++) {
-		WORD color = *src++;
-		*dst = color & 0xFFF0;
-		if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-		    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-		    *dst |= color & 0x000F;
-		dst++;
+	    for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+		    WORD color = *src++;
+		    *dst = color & 0xFFF0;
+		    if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			*dst |= color & 0x000F;
+		    dst++;
+		}
+		src += line_increase;
 	    }
 	} break;
 	
         case CONVERT_CK_4444_ARGB: {
 	    /* Move the four Alpha bits... */
-	    DWORD i;
+	    int x, y;
 	    WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
 	    
 	    if (*temp_buffer == NULL)
@@ -997,18 +1021,21 @@
 					 current_tex_width * current_tex_height * sizeof(WORD));
 	    dst = (WORD *) *temp_buffer;
 	    
-	    for (i = 0; i < height * width; i++) {
-		WORD color = *src++;
-		*dst = (color & 0x0FFF) << 4;
-		if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-		    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-		    *dst |= (color & 0xF000) >> 12;
-		dst++;
+	    for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+		    WORD color = *src++;
+		    *dst = (color & 0x0FFF) << 4;
+		    if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			*dst |= (color & 0xF000) >> 12;
+		    dst++;
+		}
+		src += line_increase;
 	    }
 	} break;
 	
         case CONVERT_CK_1555: {
-	    DWORD i;
+	    int x, y;
 	    WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
 	    
 	    if (*temp_buffer == NULL)
@@ -1016,19 +1043,22 @@
 					 current_tex_width * current_tex_height * sizeof(WORD));
 	    dst = (WORD *) *temp_buffer;
 	    
-	    for (i = 0; i < height * width; i++) {
-		WORD color = *src++;
-		*dst = (color & 0x7FFF) << 1;
-		if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-		    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-		    *dst |= (color & 0x8000) >> 15;
-		dst++;
+	    for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+		    WORD color = *src++;
+		    *dst = (color & 0x7FFF) << 1;
+		    if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			*dst |= (color & 0x8000) >> 15;
+		    dst++;
+		}
+		src += line_increase;
 	    }
 	} break;
 	
         case CONVERT_555: {
 	    /* Converting the 0555 format in 5551 packed */
-	    DWORD i;
+	    int x, y;
 	    WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
 	    
 	    if (*temp_buffer == NULL)
@@ -1037,18 +1067,24 @@
 	    dst = (WORD *) *temp_buffer;
 	    
 	    if (src_d->dwFlags & DDSD_CKSRCBLT) {
-		for (i = 0; i < height * width; i++) {
-		    WORD color = *src++;
-		    *dst = (color & 0x7FFF) << 1;
-		    if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-			*dst |= 0x0001;
-		    dst++;
+		for (y = 0; y < height; y++) {
+		    for (x = 0; x < width; x++) {
+			WORD color = *src++;
+			*dst = (color & 0x7FFF) << 1;
+			if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			    *dst |= 0x0001;
+			dst++;
+		    }
+		    src += line_increase;
 		}
 	    } else {
-		for (i = 0; i < height * width; i++) {
-		    WORD color = *src++;
-		    *dst++ = ((color & 0x7FFF) << 1) | 0x0001;
+		for (y = 0; y < height; y++) {
+		    for (x = 0; x < width; x++) {
+			WORD color = *src++;
+			*dst++ = ((color & 0x7FFF) << 1) | 0x0001;
+		    }
+		    src += line_increase;
 		}
 	    }
 	    
@@ -1056,7 +1092,7 @@
 	
         case CONVERT_CK_RGB24: {
 	    /* This is a pain :-) */
-	    DWORD i;
+	    int x, y;
 	    BYTE *src = (BYTE *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top));
 	    DWORD *dst;
 	    
@@ -1065,20 +1101,23 @@
 					 current_tex_width * current_tex_height * sizeof(DWORD));
 	    dst = (DWORD *) *temp_buffer;
 
-	    for (i = 0; i < height * width; i++) {
-		DWORD color = *((DWORD *) src) & 0x00FFFFFF;
-		src += 3;
-		*dst = *src++ << 8;
-		if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-		    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-		    *dst |= 0xFF;
-		dst++;
+	    for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+		    DWORD color = *((DWORD *) src) & 0x00FFFFFF;
+		    src += 3;
+		    *dst = *src++ << 8;
+		    if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			*dst |= 0xFF;
+		    dst++;
+		}
+		src += 3 * line_increase;
 	    }
 	} break;
 
         case CONVERT_CK_8888: {
 	    /* Just use the alpha component to handle color-keying... */
-	    DWORD i;
+	    int x, y;
 	    DWORD *src = (DWORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
 	    
 	    if (*temp_buffer == NULL)
@@ -1086,18 +1125,21 @@
 					 current_tex_width * current_tex_height * sizeof(DWORD));	    
 	    dst = (DWORD *) *temp_buffer;
 	    
-	    for (i = 0; i < height * width; i++) {
-		DWORD color = *src++;
-		*dst = color & 0xFFFFFF00;
-		if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-		    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-		    *dst |= color & 0x000000FF;
-		dst++;
+	    for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+		    DWORD color = *src++;
+		    *dst = color & 0xFFFFFF00;
+		    if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			*dst |= color & 0x000000FF;
+		    dst++;
+		}
+		src += line_increase;
 	    }
 	} break;
 	
         case CONVERT_CK_8888_ARGB: {
-	    DWORD i;
+	    int x, y;
 	    DWORD *src = (DWORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
 	    
 	    if (*temp_buffer == NULL)
@@ -1105,19 +1147,22 @@
 					 current_tex_width * current_tex_height * sizeof(DWORD));	    
 	    dst = (DWORD *) *temp_buffer;
 	    
-	    for (i = 0; i < height * width; i++) {
-		DWORD color = *src++;
-		*dst = (color & 0x00FFFFFF) << 8;
-		if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-		    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-		    *dst |= (color & 0xFF000000) >> 24;
-		dst++;
+	    for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+		    DWORD color = *src++;
+		    *dst = (color & 0x00FFFFFF) << 8;
+		    if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			*dst |= (color & 0xFF000000) >> 24;
+		    dst++;
+		}
+		src += line_increase;
 	    }
 	} break;
 	
         case CONVERT_RGB32_888: {
 	    /* Just add an alpha component and handle color-keying... */
-	    DWORD i;
+	    int x, y;
 	    DWORD *src = (DWORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
 	    
 	    if (*temp_buffer == NULL)
@@ -1126,29 +1171,39 @@
 	    dst = (DWORD *) *temp_buffer;
 	    
 	    if (src_d->dwFlags & DDSD_CKSRCBLT) {
-		for (i = 0; i < height * width; i++) {
-		    DWORD color = *src++;
-		    *dst = color << 8;
-		    if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-			*dst |= 0xFF;
-		    dst++;
+		for (y = 0; y < height; y++) {
+		    for (x = 0; x < width; x++) {
+			DWORD color = *src++;
+			*dst = color << 8;
+			if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			    *dst |= 0xFF;
+			dst++;
+		    }
+		    src += line_increase;
 		}
 	    } else {
-		for (i = 0; i < height * width; i++) {
-		    *dst++ = (*src++ << 8) | 0xFF;
+		for (y = 0; y < height; y++) {
+		    for (x = 0; x < width; x++) {
+			*dst++ = (*src++ << 8) | 0xFF;
+		    }
+		    src += line_increase;
 		}
 	    }
 	} break;
 
         case NO_CONVERSION:
-	    /* Nothing to do here as the name suggests... This just prevents a compiler warning */
+	    /* Nothing to do here as the name suggests... Just set-up the buffer correctly */
 	    surf_buffer = (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top));
 	    break;
     }
 
     if (convert_type != NO_CONVERSION) {
 	surf_buffer = *temp_buffer;
+	if (width != current_tex_width) {
+	    /* Overide the default PixelStore parameter if only using part of the actual texture */
+	    glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
+	}
     }
     
     glTexSubImage2D(GL_TEXTURE_2D,
--- dlls/ddraw_CVS/mesa_private.h	Mon Jun  2 22:26:33 2003
+++ dlls/ddraw/mesa_private.h	Tue Jun  3 21:16:04 2003
@@ -100,6 +100,11 @@
     GL_TRANSFORM_VERTEXBUFFER
 } GL_TRANSFORM_STATE;
 
+typedef enum {
+    WINE_GL_BUFFER_BACK = 0,
+    WINE_GL_BUFFER_FRONT
+} WINE_GL_BUFFER_TYPE;
+
 typedef struct IDirect3DDeviceGLImpl
 {
     struct IDirect3DDeviceImpl parent;
@@ -124,9 +129,13 @@
     GLuint unlock_tex;
     void *surface_ptr;
     GLenum current_internal_format;
-    
-    SURFACE_STATE state, front_state;
-    IDirectDrawSurfaceImpl *lock_surf, *front_lock_surf;
+
+    /* 0 is back-buffer, 1 is front-buffer */
+    SURFACE_STATE state[2];
+    IDirectDrawSurfaceImpl *lock_surf[2];
+    RECT lock_rect[2];
+    /* This is just here to print-out a nice warning if we have two successive locks */
+    BOOLEAN lock_rect_valid[2];
 } IDirect3DDeviceGLImpl;
 
 /* This is for the OpenGL additions... */


More information about the wine-patches mailing list