Fake texture memory usage tracking

Lionel Ulmer lionel.ulmer at free.fr
Tue Nov 26 14:49:30 CST 2002


Hi all,

This adds 'fake' texture memory usage tracking to D3D. This enables some
anal retentive game like SystemShock2 to actually go further than the driver
test. This should be done better (for example via a configure key) but for
the moment, it's enough.

Changelog:
 - fix texture snooping (plus adds snoop for 1555 format)
 - add texture memory usage tracking

-- 
		 Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
--- ../wine_work_base/dlls/ddraw/d3d_private.h	Sat Nov 23 20:45:28 2002
+++ dlls/ddraw/d3d_private.h	Tue Nov 26 21:37:43 2002
@@ -106,6 +106,7 @@
     IDirect3DImpl *d3d;
     IDirect3DDeviceImpl *d3ddevice;
     IDirectDrawSurfaceImpl *surface;
+    BOOL loaded;
 };
 
 /*****************************************************************************
--- ../wine_work_base/dlls/ddraw/d3dtexture.c	Mon Nov 25 22:05:54 2002
+++ dlls/ddraw/d3dtexture.c	Tue Nov 26 21:39:02 2002
@@ -47,12 +47,12 @@
 	char buf[32];										\
 	int x, y;										\
 												\
-	sprintf(buf, "%ld.pnm", dtpriv->tex_name);						\
+	sprintf(buf, "%ld.pnm", glThis->tex_name);						\
 	f = fopen(buf, "wb");									\
 	fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight);			\
 	for (y = 0; y < src_d->dwHeight; y++) {							\
 	  for (x = 0; x < src_d->dwWidth; x++) {						\
-	    unsigned char c = ((unsigned char *) src_d->y.lpSurface)[y * src_d->dwWidth + x];	\
+	    unsigned char c = ((unsigned char *) src_d->lpSurface)[y * src_d->dwWidth + x];	\
 	    fputc(table[c][0], f);								\
 	    fputc(table[c][1], f);								\
 	    fputc(table[c][2], f);								\
@@ -67,12 +67,12 @@
 	    char buf[32];										\
 	    int x, y;											\
 	    												\
-	    sprintf(buf, "%ld.pnm", dtpriv->tex_name);							\
+	    sprintf(buf, "%ld.pnm", glThis->tex_name);							\
 	    f = fopen(buf, "wb");									\
 	    fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight);				\
 	    for (y = 0; y < src_d->dwHeight; y++) {							\
 	      for (x = 0; x < src_d->dwWidth; x++) {							\
-		unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x];	\
+		unsigned short c = ((unsigned short *) src_d->lpSurface)[y * src_d->dwWidth + x];	\
 		fputc((c & 0xF800) >> 8, f);								\
 		fputc((c & 0x07E0) >> 3, f);								\
 		fputc((c & 0x001F) << 3, f);								\
@@ -87,12 +87,12 @@
 	    char buf[32];										\
 	    int x, y;											\
 	    												\
-	    sprintf(buf, "%ld.pnm", dtpriv->tex_name);							\
+	    sprintf(buf, "%ld.pnm", glThis->tex_name);							\
 	    f = fopen(buf, "wb");									\
 	    fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight);				\
 	    for (y = 0; y < src_d->dwHeight; y++) {							\
 	      for (x = 0; x < src_d->dwWidth; x++) {							\
-		unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x];	\
+		unsigned short c = ((unsigned short *) src_d->lpSurface)[y * src_d->dwWidth + x];	\
 		fputc((c & 0xF800) >> 8, f);								\
 		fputc((c & 0x07C0) >> 3, f);								\
 		fputc((c & 0x003E) << 2, f);								\
@@ -100,10 +100,31 @@
 	    }												\
 	    fclose(f);											\
 	  }
+
+#define SNOOP_1555()											\
+	  {												\
+	    FILE *f;											\
+	    char buf[32];										\
+	    int x, y;											\
+	    												\
+	    sprintf(buf, "%ld.pnm", glThis->tex_name);							\
+	    f = fopen(buf, "wb");									\
+	    fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight);				\
+	    for (y = 0; y < src_d->dwHeight; y++) {							\
+	      for (x = 0; x < src_d->dwWidth; x++) {							\
+		unsigned short c = ((unsigned short *) src_d->lpSurface)[y * src_d->dwWidth + x];	\
+		fputc((c & 0x7C00) >> 7, f);								\
+		fputc((c & 0x03E0) >> 2, f);								\
+		fputc((c & 0x001F) << 3, f);								\
+	      }												\
+	    }												\
+	    fclose(f);											\
+	  }
 #else
 #define SNOOP_PALETTED()
 #define SNOOP_5650()
 #define SNOOP_5551()
+#define SNOOP_1555()
 #endif
 
 /*******************************************************************************
@@ -304,6 +325,8 @@
     FIXME("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
     
     if (!--(This->ref)) {
+        DWORD mem_used;
+      
         /* Release surface */
         IDirectDrawSurface3_Release(ICOM_INTERFACE(This->surface, IDirectDrawSurface3));
 
@@ -316,7 +339,13 @@
 	if (This->d3ddevice != NULL)
 	    if (This->d3ddevice->current_texture == This)
 	        This->d3ddevice->current_texture = NULL;
-	
+
+	if (This->loaded) {
+	    mem_used = This->surface->surface_desc.dwHeight *
+	               This->surface->surface_desc.dwHeight *
+		       This->surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount;
+	    This->surface->ddraw_owner->free_memory(This->surface->ddraw_owner, mem_used);
+	}
 	HeapFree(GetProcessHeap(),0,This);
 	return 0;
     }
@@ -368,6 +397,7 @@
     ICOM_THIS_FROM(IDirect3DTextureImpl, IDirect3DTexture2, iface);
     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This;
     IDirect3DTextureImpl *lpD3DTextureImpl = ICOM_OBJECT(IDirect3DTextureImpl, IDirect3DTexture2, lpD3DTexture2);
+    DWORD mem_used;
     DDSURFACEDESC	*src_d, *dst_d;
     static void (*ptr_ColorTableEXT) (GLenum target, GLenum internalformat,
 				      GLsizei width, GLenum format, GLenum type, const GLvoid *table) = NULL;
@@ -376,6 +406,16 @@
 #endif
     
     TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DTexture2);
+
+    mem_used = This->surface->surface_desc.dwHeight *
+               This->surface->surface_desc.dwHeight *
+	       This->surface->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount;
+    if (This->surface->ddraw_owner->allocate_memory(This->surface->ddraw_owner, mem_used) < 0) {
+        TRACE(" out of virtual memory... Warning application.\n");
+	return D3DERR_TEXTURE_LOAD_FAILED;
+    }
+    This->loaded = TRUE;
+    
     TRACE("Copied surface %p to surface %p\n", lpD3DTextureImpl->surface, This->surface);
 
     if ( This->surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD )
@@ -559,6 +599,7 @@
 				  ((*src & 0x7FFF) <<  1));
 			src++;
 		    }
+		    SNOOP_1555();
 		    
 		    glTexImage2D(GL_TEXTURE_2D,
 				 0,
--- ../wine_work_base/dlls/ddraw/ddraw_private.h	Mon Nov 25 22:05:54 2002
+++ dlls/ddraw/ddraw_private.h	Tue Nov 26 21:18:34 2002
@@ -151,6 +151,14 @@
     pixel_convert_func pixel_convert;
     palette_convert_func palette_convert;
 
+    /* Use to fool some too strict games */
+    INT32 (*allocate_memory)(IDirectDrawImpl *This, DWORD mem);
+    void (*free_memory)(IDirectDrawImpl *This, DWORD mem);
+    DWORD total_vidmem, available_vidmem;
+    
+    /* This is to get the D3D object associated to this DDraw object */
+    struct IDirect3DImpl *d3d;
+    
     /* This is for the fake mainWindow */
     ATOM	winclass;
     PAINTSTRUCT	ps;
@@ -239,6 +247,7 @@
 
     HDC hDC;
     RECT lastlockrect;
+    DWORD lastlocktype;
     BOOL dc_in_use;
 
     HRESULT (*duplicate_surface)(IDirectDrawSurfaceImpl* src,
@@ -276,12 +285,14 @@
 
     /* Everything below here is dodgy. */
     /* For Direct3D use */
-    LPVOID			aux_ctx, aux_data;
+    LPVOID aux_ctx, aux_data;
     void (*aux_release)(LPVOID ctx, LPVOID data);
     BOOL (*aux_flip)(LPVOID ctx, LPVOID data);
     void (*aux_unlock)(LPVOID ctx, LPVOID data, LPRECT lpRect);
     struct IDirect3DTextureImpl *texture;
     HRESULT (WINAPI *SetColorKey_cb)(struct IDirect3DTextureImpl *texture, DWORD dwFlags, LPDDCOLORKEY ckey ) ;
+    /* This is to get the D3DDevice object associated to this surface */
+    struct IDirect3DDeviceImpl *d3ddevice;
 };
 
 /*****************************************************************************
--- ../wine_work_base/dlls/ddraw/ddraw/main.c	Mon Nov 25 22:05:54 2002
+++ dlls/ddraw/ddraw/main.c	Tue Nov 26 21:26:58 2002
@@ -58,6 +58,10 @@
 static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl* This);
 static void LosePrimarySurface(IDirectDrawImpl* This);
 
+static INT32 allocate_memory(IDirectDrawImpl *This, DWORD mem) ;
+static void free_memory(IDirectDrawImpl *This, DWORD mem) ;
+
+
 static const char ddProp[] = "WINE_DDRAW_Property";
 
 /* Not called from the vtable. */
@@ -84,6 +88,12 @@
     ICOM_INIT_INTERFACE(This, IDirectDraw4, DDRAW_IDirectDraw4_VTable);
     /* There is no generic implementation of IDD7 */
 
+    /* This is for the moment here... */
+    This->free_memory = free_memory;
+    This->allocate_memory = allocate_memory;
+    This->total_vidmem = 16 * 1024 * 1024;
+    This->available_vidmem = This->total_vidmem;
+      
     return DD_OK;
 }
 
@@ -177,6 +187,9 @@
 
 	*obj = ICOM_INTERFACE(d3d_impl, IDirect3D);
 
+	/* And store the D3D object */
+	This->d3d = d3d_impl;
+	
 	TRACE(" returning Direct3D interface at %p.\n", *obj);
     }
     else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
@@ -1099,6 +1112,18 @@
     return DD_OK;
 }
 
+static INT32 allocate_memory(IDirectDrawImpl *This, DWORD mem)
+{
+    if (mem > This->available_vidmem) return -1;
+    This->available_vidmem -= mem;
+    return This->available_vidmem;
+}
+
+static void free_memory(IDirectDrawImpl *This, DWORD mem)
+{
+    This->available_vidmem += mem;
+}
+
 HRESULT WINAPI
 Main_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 ddscaps,
 				   LPDWORD total, LPDWORD free)
@@ -1107,8 +1132,11 @@
     TRACE("(%p)->(%p,%p,%p)\n", This,ddscaps,total,free);
 
     /* We have 16 MB videomemory */
-    if (total)	*total= 16*1024*1024;
-    if (free)	*free = 16*1024*1024;
+    if (total)	*total= This->total_vidmem;
+    if (free)	*free = This->available_vidmem;
+
+    TRACE(" returning (total) %ld / (free) %ld\n", *total, *free);
+    
     return DD_OK;
 }
 
--- ../wine_work_base/dlls/ddraw/dsurface/main.c	Mon Nov 25 22:05:54 2002
+++ dlls/ddraw/dsurface/main.c	Sun Nov 24 16:43:53 2002
@@ -175,7 +175,7 @@
         IDirect3DDeviceImpl *d3ddevimpl;
 	HRESULT ret_value;
 
-	ret_value = d3ddevice_create(&d3ddevimpl, NULL, This);
+	ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner->d3d, This);
 	if (FAILED(ret_value)) return ret_value;
 
 	*ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice);
@@ -991,6 +991,9 @@
 
     TRACE("locked surface returning description : \n");
     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD);
+
+    /* Used to optimize the D3D Device locking */
+    This->lastlocktype = flags & (DDLOCK_READONLY|DDLOCK_WRITEONLY);
     
     /* If asked only for a part, change the surface pointer.
      * (Not documented.) */


More information about the wine-patches mailing list