[D3D 77] Optimisations in texture handling.

Lionel Ulmer lionel.ulmer at free.fr
Fri Jan 3 11:12:28 CST 2003


Changelog:
 - some fixes / optimisations in the color keying code
 - minimize at the maximum texture uploads

-- 
		 Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
--- /home/ulmer/Wine/wine_base//dlls/ddraw/d3ddevice/mesa.c	2003-01-03 14:30:30.000000000 +0100
+++ /home/ulmer/Wine/wine_work//dlls/ddraw/d3ddevice/mesa.c	2003-01-03 15:58:15.000000000 +0100
@@ -1413,15 +1413,13 @@
         glDisable(GL_TEXTURE_2D);
     } else {
         IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
-	IDirect3DTextureGLImpl *tex_glimpl = (IDirect3DTextureGLImpl *) tex_impl->tex_private;
 	
 	This->current_texture[dwStage] = tex_impl;
 	IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
 	
-	TRACE(" activating OpenGL texture %d.\n", tex_glimpl->tex_name);
-	
         glEnable(GL_TEXTURE_2D);
-	glBindTexture(GL_TEXTURE_2D, tex_glimpl->tex_name);
+	gltex_upload_texture(tex_impl);
+
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glThis->render_state.mag);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glThis->render_state.min);
     }
--- /home/ulmer/Wine/wine_base//dlls/ddraw/d3dtexture.c	2003-01-03 14:30:30.000000000 +0100
+++ /home/ulmer/Wine/wine_work//dlls/ddraw/d3dtexture.c	2003-01-03 15:59:29.000000000 +0100
@@ -61,10 +61,9 @@
 /*******************************************************************************
  *			   IDirectSurface callback methods
  */
-static HRESULT
-gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
+HRESULT
+gltex_upload_texture(IDirectDrawSurfaceImpl *This) {
     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
-    GLuint current_texture;
 #if 0
     static BOOL color_table_queried = FALSE;
 #endif
@@ -77,11 +76,15 @@
 
     DDSURFACEDESC *src_d = (DDSURFACEDESC *)&(This->surface_desc);
 
-    TRACE(" uploading texture to GL id %d (initial = %d).\n", glThis->tex_name, init_upload);
-
-    glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
     glBindTexture(GL_TEXTURE_2D, glThis->tex_name);
 
+    if (glThis->dirty_flag == FALSE) {
+        TRACE(" activating OpenGL texture id %d.\n", glThis->tex_name);
+	return DD_OK;
+    } else {
+        TRACE(" activating and uploading texture id %d (initial done = %d).\n", glThis->tex_name, glThis->initial_upload_done);
+    }
+
     /* Texture snooping for the curious :-) */
     snoop_texture(This);
     
@@ -272,14 +275,21 @@
 		surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
 		dst = surface;
 		
-		for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
-		    WORD color = *src++;
-		    *dst = (color & 0x0FFF) << 4;
-		    if (((src_d->dwFlags & DDSD_CKSRCBLT) == 0) ||
-			(color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-		        *dst |= (color & 0xF000) >> 12;
-		    dst++;
+		if (src_d->dwFlags & DDSD_CKSRCBLT) {
+		    for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
+		        WORD color = *src++;
+			*dst = (color & 0x0FFF) << 4;
+			if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			    *dst |= (color & 0xF000) >> 12;
+			dst++;
+		    }
+		} else {
+		    for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
+		        WORD color = *src++;
+			*dst++ = (((color & 0x0FFF) << 4) |
+				  ((color & 0xF000) >> 12));
+		    }
 		}
 
 	        format = GL_RGBA;
@@ -294,14 +304,22 @@
 		
 		surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
 		dst = (WORD *) surface;
-		for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
-		    WORD color = *src++;
-		    *dst = (color & 0x7FFF) << 1;
-		    if (((src_d->dwFlags & DDSD_CKSRCBLT) == 0) ||
-			(color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
-			(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
-		        *dst |= (color & 0x8000) >> 15;
-		    dst++;
+		
+		if (src_d->dwFlags & DDSD_CKSRCBLT) {
+		    for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
+		        WORD color = *src++;
+			*dst = (color & 0x7FFF) << 1;
+			if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
+			    (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
+			    *dst |= (color & 0x8000) >> 15;
+			dst++;
+		    }
+		} else {
+		    for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
+		        WORD color = *src++;
+			*dst++ = (((color & 0x7FFF) << 1) |
+				  ((color & 0x8000) >> 15));
+		    }		  
 		}
 		
 	        format = GL_RGBA;
@@ -367,13 +385,14 @@
 		       (src_d->ddpfPixelFormat.u3.dwGBitMask ==        0x0000FF00) &&
 		       (src_d->ddpfPixelFormat.u4.dwBBitMask ==        0x000000FF) &&
 		       (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
-	        if (src_d->dwFlags & DDSD_CKSRCBLT) {
-		    /* Just add an alpha component and handle color-keying... */
-		    DWORD i;
-		    DWORD *src = (DWORD *) src_d->lpSurface, *dst;
+	        /* Just add an alpha component and handle color-keying... */
+	        DWORD i;
+		DWORD *src = (DWORD *) src_d->lpSurface, *dst;
 		
-		    surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
-		    dst = (DWORD *) surface;
+		surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
+		dst = (DWORD *) surface;
+		
+	        if (src_d->dwFlags & DDSD_CKSRCBLT) {
 		    for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
 		        DWORD color = *src++;
 		        *dst = color << 8;
@@ -382,6 +401,10 @@
 			    *dst |= 0xFF;
 			dst++;
 		    }
+		} else {
+		    for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
+		        *dst++ = (*src++ << 8) | 0xFF;
+		    }
 		}
 	        format = GL_RGBA;
 		pixel_format = GL_UNSIGNED_INT_8_8_8_8;
@@ -396,7 +419,7 @@
     } 
 
     if ((upload_done == FALSE) && (error == FALSE)) {
-        if (init_upload)
+        if (glThis->initial_upload_done == FALSE) {
 	    glTexImage2D(GL_TEXTURE_2D,
 			 This->mipmap_level,
 			 format,
@@ -405,7 +428,8 @@
 			 format,
 			 pixel_format,
 			 surface == NULL ? src_d->lpSurface : surface);
-	else
+	    glThis->initial_upload_done = TRUE;
+	} else {
 	    glTexSubImage2D(GL_TEXTURE_2D,
 			    This->mipmap_level,
 			    0, 0,
@@ -413,6 +437,8 @@
 			    format,
 			    pixel_format,
 			    surface == NULL ? src_d->lpSurface : surface);
+	}
+	
 	if (surface) HeapFree(GetProcessHeap(), 0, surface);
     } else if (error == TRUE) {
 	if (ERR_ON(ddraw)) {
@@ -421,7 +447,8 @@
 	}
     }
 
-    glBindTexture(GL_TEXTURE_2D, current_texture);
+    glThis->dirty_flag = FALSE;
+
     return DD_OK;
 }
 
@@ -440,12 +467,8 @@
 {
     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
 
-    /* Basically, the only thing we have to do is to re-upload the texture */
-    if (glThis->first_unlock == FALSE) {
-        ENTER_GL();
-	gltex_upload_texture(This, glThis->first_unlock);
-	LEAVE_GL();
-    }
+    glThis->dirty_flag = TRUE;
+
     return DD_OK;
 }
 
@@ -492,13 +515,9 @@
     
     /* First call the previous set_palette function */
     glThis->set_palette(This, pal);
-
-    /* Then re-upload the texture to OpenGL only if the surface was already 'unlocked' once */
-    if (glThis->first_unlock == FALSE) {
-        ENTER_GL();
-	gltex_upload_texture(This, glThis->first_unlock);
-	LEAVE_GL();
-    }
+    
+    /* And set the dirty flag */
+    glThis->dirty_flag = TRUE;
 }
 
 static void
@@ -545,10 +564,9 @@
 
     glThis->unlock_update(This, pRect);
     
-    ENTER_GL();
-    gltex_upload_texture(This, glThis->first_unlock);
-    LEAVE_GL();
-    glThis->first_unlock = FALSE;
+    /* Set the dirty flag according to the lock type */
+    if ((This->lastlocktype & DDLOCK_READONLY) == 0)
+        glThis->dirty_flag = TRUE;
 }
 
 HRESULT WINAPI
@@ -661,15 +679,8 @@
 	    /* If the GetHandle was not done, it is an error... */
 	    if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n");
 
-	    ENTER_GL();
-	    
-	    /* Now, load the texture */
-	    /* d3dd->set_context(d3dd); We need to set the context somehow.... */
-	    
-	    ret_value = gltex_upload_texture(This, glThis->first_unlock);
-	    glThis->first_unlock = FALSE;
-	    
-	    LEAVE_GL();
+	    /* Set this texture as dirty */
+	    glThis->dirty_flag = TRUE;
 	}
     }
 
@@ -823,10 +834,6 @@
 	
 	/* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL.
 	   Otherwise, it will be uploaded here (and may be invalid). */
-	if (at_creation == TRUE)
-	    private->first_unlock = TRUE;
-	else
-	    private->first_unlock = FALSE;
 	surf->final_release = gltex_final_release;
 	surf->lock_update = gltex_lock_update;
 	surf->unlock_update = gltex_unlock_update;
@@ -844,13 +851,11 @@
 	    TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n",
 		  surf, private, private->tex_name, main, main->tex_private);
 	}
-
-	if ((at_creation == FALSE) &&
-	    ((surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD) == 0))
-	{
-	    gltex_upload_texture(surf, TRUE);
-	}
 	LEAVE_GL();
+
+	/* And set the dirty flag accordingly */
+	private->dirty_flag = (at_creation == FALSE);
+	private->initial_upload_done = FALSE;
     }
 
     return D3D_OK;
--- /home/ulmer/Wine/wine_base//dlls/ddraw/mesa.c	2003-01-03 14:30:30.000000000 +0100
+++ /home/ulmer/Wine/wine_work//dlls/ddraw/mesa.c	2003-01-03 15:58:28.000000000 +0100
@@ -86,16 +86,15 @@
 		    glDisable(GL_TEXTURE_2D);
 		    TRACE("disabling texturing\n");
 		} else {
-		    IDirect3DTextureGLImpl *gl_tex = (IDirect3DTextureGLImpl *) tex->tex_private;
-		    
 		    glEnable(GL_TEXTURE_2D);
+		    
 		    /* Default parameters */
-		    glBindTexture(GL_TEXTURE_2D, gl_tex->tex_name);
+		    gltex_upload_texture(tex);
+		    
 		    /* To prevent state change, we could test here what are the parameters
 		       stored in the texture */
 		    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, rs->mag);
 		    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, rs->min);
-		    TRACE("setting OpenGL texture handle : %d\n", gl_tex->tex_name);
 		}
 	    } break;
 
--- /home/ulmer/Wine/wine_base//dlls/ddraw/mesa_private.h	2003-01-02 18:01:43.000000000 +0100
+++ /home/ulmer/Wine/wine_work//dlls/ddraw/mesa_private.h	2003-01-03 15:52:58.000000000 +0100
@@ -102,7 +102,11 @@
 {
     GLuint tex_name;
     BOOLEAN loaded; /* For the moment, this is here.. Should be part of surface management though */
-    BOOLEAN first_unlock;
+
+    /* Texture upload management */
+    BOOLEAN initial_upload_done;
+    BOOLEAN dirty_flag;
+
     /* This is for now used to override 'standard' surface stuff to be as transparent as possible */
     void (*final_release)(struct IDirectDrawSurfaceImpl *This);
     void (*lock_update)(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags);
@@ -157,6 +161,9 @@
 extern HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context) ;
 extern HRESULT d3ddevice_find(IDirect3DImpl *d3d, LPD3DFINDDEVICESEARCH lpD3DDFS, LPD3DFINDDEVICERESULT lplpD3DDevice);
 
+/* Used to upload the texture */
+extern HRESULT gltex_upload_texture(IDirectDrawSurfaceImpl *This) ;
+
 /* Common functions defined in d3dcommon.c */
 void set_render_state(IDirect3DDeviceGLImpl* This,
 		      D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState);


More information about the wine-patches mailing list