[D3D] Added native and emulated S3TC support (take 2)

Christian Costa titan.costa at wanadoo.fr
Thu Jul 29 17:49:33 CDT 2004


Hi,

This is the second version of my patch which take into account Lionel's 
comments plus another fix.

I've only mentionned the libtxc_dxtn.so library for software 
decompression when the video card does not support S3TC.
Maybe Lionel can say if we can add more precise information i.e 
reference to the DRI project.

Bye,

Changelog:
Added native and emulated S3TC support.

Christian Costa   titan.costa at wanadoo.fr

-------------- next part --------------
Index: d3d_private.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/d3d_private.h,v
retrieving revision 1.38
diff -u -r1.38 d3d_private.h
--- d3d_private.h	15 Sep 2003 20:00:03 -0000	1.38
+++ d3d_private.h	29 Jul 2004 21:45:49 -0000
@@ -276,4 +276,12 @@
 
 extern const float id_mat[16];
 
+typedef void (*FUNC_FETCH_2D_TEXEL_RGBA_DXT1)(int srcRowStride, const BYTE *pixdata, int i, int j, void *texel);
+typedef void (*FUNC_FETCH_2D_TEXEL_RGBA_DXT3)(int srcRowStride, const BYTE *pixdata, int i, int j, void *texel);
+typedef void (*FUNC_FETCH_2D_TEXEL_RGBA_DXT5)(int srcRowStride, const BYTE *pixdata, int i, int j, void *texel);
+
+extern FUNC_FETCH_2D_TEXEL_RGBA_DXT1 fetch_2d_texel_rgba_dxt1;
+extern FUNC_FETCH_2D_TEXEL_RGBA_DXT3 fetch_2d_texel_rgba_dxt3;
+extern FUNC_FETCH_2D_TEXEL_RGBA_DXT5 fetch_2d_texel_rgba_dxt5;
+
 #endif /* __GRAPHICS_WINE_D3D_PRIVATE_H */
Index: d3dtexture.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/d3dtexture.c,v
retrieving revision 1.62
diff -u -r1.62 d3dtexture.c
--- d3dtexture.c	12 Apr 2004 22:07:33 -0000	1.62
+++ d3dtexture.c	29 Jul 2004 21:45:50 -0000
@@ -642,7 +642,11 @@
 	if (gl_dst_ptr != NULL) {
 	    if (gl_dst_ptr->loaded == FALSE) {
 	        /* Only check memory for not already loaded texture... */
-	        DWORD mem_used = dst_ptr->surface_desc.dwHeight * dst_ptr->surface_desc.u1.lPitch;
+	        DWORD mem_used;
+		if (dst_ptr->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
+                    mem_used = dst_ptr->surface_desc.u1.dwLinearSize;
+		else
+                    mem_used = dst_ptr->surface_desc.dwHeight * dst_ptr->surface_desc.u1.lPitch;
 		if (This->ddraw_owner->allocate_memory(This->ddraw_owner, mem_used) < 0) {
 		    TRACE(" out of virtual memory... Warning application.\n");
 		    return D3DERR_TEXTURE_LOAD_FAILED;
@@ -697,7 +701,10 @@
 
 	    /* Copy the main memory texture into the surface that corresponds to the OpenGL
 	       texture object. */
-	    memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight);
+	    if (dst_ptr->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
+	        memcpy(dst_d->lpSurface, src_d->lpSurface, src_ptr->surface_desc.u1.dwLinearSize);
+	    else
+	        memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight);
 
 	    if (gl_dst_ptr != NULL) {
 	        /* If the GetHandle was not done, it is an error... */
Index: ddraw_private.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/ddraw_private.h,v
retrieving revision 1.42
diff -u -r1.42 ddraw_private.h
--- ddraw_private.h	12 Apr 2004 22:07:33 -0000	1.42
+++ ddraw_private.h	29 Jul 2004 21:45:51 -0000
@@ -55,6 +55,8 @@
 		(to)->dwSize = __size;/*restore size*/	\
 	} while (0)
 
+#define MAKE_FOURCC(a,b,c,d) ((a << 0) | (b << 8) | (c << 16) | (d << 24))
+
 /*****************************************************************************
  * IDirectDraw implementation structure
  */
@@ -377,6 +379,7 @@
 extern Convert ModeEmulations[8];
 extern int _common_depth_to_pixelformat(DWORD depth,LPDIRECTDRAW ddraw);
 extern BOOL opengl_initialized;
+extern BOOL s3tc_initialized;
 
 /******************************************************************************
  * Structure conversion (for thunks)
Index: main.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/main.c,v
retrieving revision 1.40
diff -u -r1.40 main.c
--- main.c	7 Apr 2004 03:59:41 -0000	1.40
+++ main.c	29 Jul 2004 21:45:55 -0000
@@ -86,7 +86,6 @@
 static BOOL DDRAW_bind_to_opengl( void )
 {
     const char *glname = SONAME_LIBGL;
-    BOOL ret_value;
 
     gl_handle = wine_dlopen(glname, RTLD_NOW, NULL, 0);
     if (!gl_handle) {
@@ -104,11 +103,7 @@
 #undef GL_API_FUNCTION
 
     /* And now calls the function to initialize the various fields for the rendering devices */
-    ret_value = d3ddevice_init_at_startup(gl_handle);
-
-    wine_dlclose(gl_handle, NULL, 0);
-    gl_handle = NULL;
-    return ret_value;
+    return d3ddevice_init_at_startup(gl_handle);
     
 sym_not_found:
     WARN("Wine cannot find certain functions that it needs inside the OpenGL\n"
@@ -121,6 +116,49 @@
 
 #endif /* HAVE_OPENGL */
 
+BOOL s3tc_initialized = 0;
+
+static void *s3tc_handle = NULL;
+
+FUNC_FETCH_2D_TEXEL_RGBA_DXT1 fetch_2d_texel_rgba_dxt1;
+FUNC_FETCH_2D_TEXEL_RGBA_DXT3 fetch_2d_texel_rgba_dxt3;
+FUNC_FETCH_2D_TEXEL_RGBA_DXT5 fetch_2d_texel_rgba_dxt5;
+
+#ifndef SONAME_LIBS3TC
+#define SONAME_LIBS3TC "libtxc_dxtn.so"
+#endif
+
+static BOOL DDRAW_bind_to_s3tc( void )
+{
+    const char *s3tcname = SONAME_LIBS3TC;
+
+    s3tc_handle = wine_dlopen(s3tcname, RTLD_NOW, NULL, 0);
+    if (!s3tc_handle) {
+        TRACE("No S3TC software decompression library seems to be present (%s).\n",s3tcname);
+	return FALSE;
+    }
+    TRACE("Found S3TC software decompression library (%s).\n",s3tcname);
+
+#define API_FUNCTION(f)  \
+    if((f = wine_dlsym(s3tc_handle, #f, NULL, 0)) == NULL) \
+    { \
+        WARN("Can't find symbol %s\n", #f); \
+        goto sym_not_found; \
+    }
+    API_FUNCTION(fetch_2d_texel_rgba_dxt1);
+    API_FUNCTION(fetch_2d_texel_rgba_dxt3);
+    API_FUNCTION(fetch_2d_texel_rgba_dxt5);
+#undef API_FUNCTION
+
+    return TRUE;
+    
+sym_not_found:
+    WARN("Wine cannot find functions that are necessary for S3TC software decompression\n");
+    wine_dlclose(s3tc_handle, NULL, 0);
+    s3tc_handle = NULL;
+    return FALSE;
+}
+
 /***********************************************************************
  *		DirectDrawEnumerateExA (DDRAW.@)
  */
@@ -607,6 +645,7 @@
 #ifdef HAVE_OPENGL
         opengl_initialized = DDRAW_bind_to_opengl();
 #endif /* HAVE_OPENGL */
+        s3tc_initialized = DDRAW_bind_to_s3tc();
     }
 
     if (DDRAW_num_drivers > 0)
Index: mesa.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/mesa.c,v
retrieving revision 1.60
diff -u -r1.60 mesa.c
--- mesa.c	27 Mar 2004 01:36:26 -0000	1.60
+++ mesa.c	29 Jul 2004 21:45:57 -0000
@@ -654,6 +654,31 @@
     current_surface = surf_ptr;
     current_level = level;
 
+    if (src_pf->dwFlags & DDPF_FOURCC) {
+	GLenum retVal;
+	int size = surf_ptr->surface_desc.u1.dwLinearSize;
+	int width = surf_ptr->surface_desc.dwWidth;
+	int height = surf_ptr->surface_desc.dwHeight;
+	LPVOID buffer = surf_ptr->surface_desc.lpSurface;
+
+	switch (src_pf->dwFourCC) {
+	    case MAKE_FOURCC('D','X','T','1'): retVal = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
+	    case MAKE_FOURCC('D','X','T','3'): retVal = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
+	    case MAKE_FOURCC('D','X','T','5'): retVal = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
+	    default:
+		FIXME("FourCC Not supported\n");
+		return DD_OK;
+		break;
+	}
+
+	if (GL_extensions.s3tc_compressed_texture) {
+	    GL_extensions.glCompressedTexImage2D(GL_TEXTURE_2D, current_level, retVal, width, height, 0, size, buffer);
+	} else
+	    ERR("Trying to upload S3TC texture whereas the device does not have support for it\n");
+
+	return DD_OK;
+    }
+
     /* First, do some sanity checks ... */
     if ((surf_ptr->surface_desc.u1.lPitch % bpp) != 0) {
 	FIXME("Warning : pitch is not a multiple of BPP - not supported yet !\n");
@@ -932,6 +957,32 @@
     width = rect->right - rect->left;
     height = rect->bottom - rect->top;
 
+    if (current_surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
+	GLint retVal;
+	int size = current_surface->surface_desc.u1.dwLinearSize;
+	int width_ = current_surface->surface_desc.dwWidth;
+	int height_ = current_surface->surface_desc.dwHeight;
+	LPVOID buffer = current_surface->surface_desc.lpSurface;
+
+	switch (current_surface->surface_desc.u4.ddpfPixelFormat.dwFourCC) {
+	    case MAKE_FOURCC('D','X','T','1'): retVal = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
+	    case MAKE_FOURCC('D','X','T','3'): retVal = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
+	    case MAKE_FOURCC('D','X','T','5'): retVal = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
+	    default:
+		FIXME("Not supported\n");
+		return DD_OK;
+		break;
+	}
+
+	if (GL_extensions.s3tc_compressed_texture) {
+	    /* GL_extensions.glCompressedTexSubImage2D(GL_TEXTURE_2D, current_level, xoffset, yoffset, width, height, retVal, (unsigned char*)temp_buffer); */
+	    GL_extensions.glCompressedTexImage2D(GL_TEXTURE_2D, current_level, retVal, width_, height_, 0, size, buffer);
+	} else
+	    ERR("Trying to upload S3TC texture whereas the device does not have support for it\n");
+
+	return DD_OK;
+    }
+    
     /* Used when converting stuff */
     line_increase = src_d->u1.lPitch - (width * bpp);
 
Index: mesa_private.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/mesa_private.h,v
retrieving revision 1.61
diff -u -r1.61 mesa_private.h
--- mesa_private.h	25 Nov 2003 00:06:33 -0000	1.61
+++ mesa_private.h	29 Jul 2004 21:45:57 -0000
@@ -175,6 +175,12 @@
     void (*glActiveTexture)(GLenum texture);
     void (*glMultiTexCoord2fv)(GLenum target, const GLfloat *v);
     void (*glClientActiveTexture)(GLenum texture);
+    /* S3TC/DXTN compressed texture */
+    BOOLEAN s3tc_compressed_texture;
+    void (*glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width,
+                                 GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+    void (*glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+                                    GLsizei width, GLsizei height, GLsizei imageSize, const GLvoid *data);
 } GL_EXTENSIONS_LIST; 
 extern GL_EXTENSIONS_LIST GL_extensions;
 
Index: d3ddevice/mesa.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/d3ddevice/mesa.c,v
retrieving revision 1.155
diff -u -r1.155 mesa.c
--- d3ddevice/mesa.c	12 Jul 2004 19:47:48 -0000	1.155
+++ d3ddevice/mesa.c	29 Jul 2004 21:46:06 -0000
@@ -614,6 +614,26 @@
     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
 
+    if (GL_extensions.s3tc_compressed_texture) {
+	TRACE("Enumerating DXT1\n");
+	pformat->dwFlags = DDPF_FOURCC;
+        pformat->dwFourCC = MAKE_FOURCC('D','X','T','1');
+	if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
+	if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
+
+	TRACE("Enumerating DXT3\n");
+	pformat->dwFlags = DDPF_FOURCC;
+        pformat->dwFourCC = MAKE_FOURCC('D','X','T','3');
+	if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
+	if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
+
+	TRACE("Enumerating DXT5\n");
+	pformat->dwFlags = DDPF_FOURCC;
+        pformat->dwFourCC = MAKE_FOURCC('D','X','T','5');
+	if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
+	if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
+    }
+
     TRACE("End of enumeration\n");
     return DD_OK;
 }
@@ -4235,6 +4255,13 @@
 	    GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
 	    GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
 	    GL_extensions.glClientActiveTexture = pglXGetProcAddressARB("glClientActiveTextureARB");
+	}
+
+	if (strstr(glExtensions, "GL_EXT_texture_compression_s3tc")) {
+	    TRACE(" - S3TC compression supported\n");
+	    GL_extensions.s3tc_compressed_texture = TRUE;
+	    GL_extensions.glCompressedTexImage2D = pglXGetProcAddressARB("glCompressedTexImage2D");
+	    GL_extensions.glCompressedTexSubImage2D = pglXGetProcAddressARB("glCompressedTexSubImage2D");
 	}
     }
     
Index: ddraw/main.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/ddraw/main.c,v
retrieving revision 1.48
diff -u -r1.48 main.c
--- ddraw/main.c	22 Mar 2004 22:57:30 -0000	1.48
+++ ddraw/main.c	29 Jul 2004 21:46:09 -0000
@@ -380,16 +380,38 @@
 	ddsd.u4.ddpfPixelFormat = This->pixelformat;
     }
 
-    /* We do not support for now compressed texture formats... */
-    if (ddsd.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
+    /* We support for now only DXT1, DXT3 & DXT5 compressed texture formats... */
+    if ((ddsd.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
+        (ddsd.u4.ddpfPixelFormat.dwFourCC != MAKE_FOURCC('D','X','T','1')) &&
+        (ddsd.u4.ddpfPixelFormat.dwFourCC != MAKE_FOURCC('D','X','T','3')) &&
+        (ddsd.u4.ddpfPixelFormat.dwFourCC != MAKE_FOURCC('D','X','T','5')) )
     {
         return DDERR_INVALIDPIXELFORMAT;
     }
-    
+
+    /* Check if we can really support DXT1, DXT3 & DXT5 */
+    if ((ddsd.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
+	!GL_extensions.s3tc_compressed_texture && !s3tc_initialized) {
+	ERR("Trying to create DXT1, DXT3 or DXT5 texture which is not supported by the video card!!!\n");
+	ERR("However there is a library libtxc_dxtn.so that can be used to do the software decompression...\n");
+        return DDERR_INVALIDPIXELFORMAT;
+    }
+
     if (!(ddsd.dwFlags & DDSD_PITCH))
     {
-	ddsd.u1.lPitch = DDRAW_width_bpp_to_pitch(ddsd.dwWidth,
-						  GET_BPP(ddsd)*8);
+	if (ddsd.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
+	    int size = 0;
+	    int width = ddsd.dwWidth;
+	    int height = ddsd.dwHeight;
+	    switch(ddsd.u4.ddpfPixelFormat.dwFourCC) {
+		case MAKE_FOURCC('D','X','T','1'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 8; break;
+		case MAKE_FOURCC('D','X','T','3'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 16; break;
+		case MAKE_FOURCC('D','X','T','5'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 16; break;
+		default: FIXME("FOURCC not supported\n"); break;
+	    }
+	    ddsd.u1.dwLinearSize = size;
+	} else
+	    ddsd.u1.lPitch = DDRAW_width_bpp_to_pitch(ddsd.dwWidth, GET_BPP(ddsd)*8);
     }
 
     /* Check also for the MIPMAP / MIPMAPCOUNT flags.
@@ -433,9 +455,23 @@
 	    if (mipmap_surface_desc.dwHeight > 1)
 		mipmap_surface_desc.dwHeight /= 2;
 
-	    mipmap_surface_desc.u1.lPitch
-		= DDRAW_width_bpp_to_pitch(mipmap_surface_desc.dwWidth,
-					   GET_BPP(ddsd)*8);
+	    if (mipmap_surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
+		int size = 0;
+		int width = mipmap_surface_desc.dwWidth;
+		int height = mipmap_surface_desc.dwHeight;
+		switch(mipmap_surface_desc.u4.ddpfPixelFormat.dwFourCC) {
+		    case MAKE_FOURCC('D','X','T','1'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 8; break;
+		    case MAKE_FOURCC('D','X','T','3'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 16; break;
+		    case MAKE_FOURCC('D','X','T','5'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 16; break;
+		    default: FIXME("FOURCC not supported\n"); break;
+		}
+		mipmap_surface_desc.u1.dwLinearSize = size;
+	    } else {
+		ddsd.u1.lPitch = DDRAW_width_bpp_to_pitch(ddsd.dwWidth, GET_BPP(ddsd)*8);
+		mipmap_surface_desc.u1.lPitch
+		    = DDRAW_width_bpp_to_pitch(mipmap_surface_desc.dwWidth,
+					       GET_BPP(ddsd)*8);
+	    }
 
 	    hr = This->create_texture(This, &mipmap_surface_desc, &mipmap,
 				      pUnkOuter, mipmap_level);
Index: dsurface/dib.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/dib.c,v
retrieving revision 1.35
diff -u -r1.35 dib.c
--- dsurface/dib.c	6 Jul 2004 18:43:10 -0000	1.35
+++ dsurface/dib.c	29 Jul 2004 21:46:11 -0000
@@ -30,6 +30,7 @@
 #include "winerror.h"
 #include "wine/debug.h"
 #include "ddraw_private.h"
+#include "d3d_private.h"
 #include "dsurface/main.h"
 #include "dsurface/dib.h"
 
@@ -254,8 +255,12 @@
 
 	This->surface_desc.dwFlags |= DDSD_PITCH|DDSD_LPSURFACE;
 
-	This->surface_desc.lpSurface
-	    = VirtualAlloc(NULL, This->surface_desc.u1.lPitch
+	if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
+	    This->surface_desc.lpSurface
+		= VirtualAlloc(NULL, This->surface_desc.u1.dwLinearSize, MEM_COMMIT, PAGE_READWRITE);
+	else
+	    This->surface_desc.lpSurface
+		= VirtualAlloc(NULL, This->surface_desc.u1.lPitch
 			   * This->surface_desc.dwHeight + 4, /* The + 4 here is for dumb games reading after the end of the surface
 								 when reading the last byte / half using word access */
 			   MEM_COMMIT, PAGE_READWRITE);
@@ -354,6 +359,26 @@
     return DD_OK;
 }
 
+void ComputeShifts(DWORD mask, DWORD* lshift, DWORD* rshift)
+{
+  int pos = 0;
+  int bits = 0;
+  *lshift = 0;
+  *rshift = 0;
+
+  if (!mask)
+    return;
+
+  while(!(mask & (1 << pos)))
+    pos++; 
+
+  while(mask & (1 << (pos+bits)))
+    bits++;
+
+  *lshift = pos;
+  *rshift = 8 - bits;
+}
+  
 HRESULT WINAPI
 DIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst,
 			  LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
@@ -393,6 +418,122 @@
     ddesc.dwSize = sizeof(ddesc);
     IDirectDrawSurface7_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
 
+    if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
+	(ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)) {
+	if (sdesc.u4.ddpfPixelFormat.dwFourCC != sdesc.u4.ddpfPixelFormat.dwFourCC) {
+	    FIXME("FOURCC->FOURCC copy only supported for the same type of surface\n");
+	    return DDERR_INVALIDPIXELFORMAT;
+	}
+	memcpy(ddesc.lpSurface, sdesc.lpSurface, ddesc.u1.dwLinearSize);
+	goto release;
+    }
+
+    if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
+	(!(ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC))) {
+	DWORD rs,rb,rm;
+	DWORD gs,gb,gm;
+	DWORD bs,bb,bm;
+	DWORD as,ab,am;
+
+	if (!s3tc_initialized) {
+	    /* FIXME: We may fake this by rendering the texture into the framebuffer using OpenGL functions and reading back
+	     *        the framebuffer. This will be slow and somewhat ugly. */ 
+	    FIXME("Manual S3TC decompression is not supported in native mode\n");
+	    goto release;
+	}
+	
+	rm = ddesc.u4.ddpfPixelFormat.u2.dwRBitMask;
+	ComputeShifts(rm, &rs, &rb);
+	gm = ddesc.u4.ddpfPixelFormat.u3.dwGBitMask;
+	ComputeShifts(gm, &gs, &gb);
+	bm = ddesc.u4.ddpfPixelFormat.u4.dwBBitMask;
+	ComputeShifts(bm, &bs, &bb);
+	am = ddesc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask;
+	ComputeShifts(am, &as, &ab);
+	if (sdesc.u4.ddpfPixelFormat.dwFourCC == MAKE_FOURCC('D','X','T','1')) {
+	    int is16 = ddesc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16;
+	    int pitch = ddesc.u1.lPitch;
+	    int width = ddesc.dwWidth;
+	    int height = ddesc.dwHeight;
+	    int x,y;
+	    char* dst = (char*) ddesc.lpSurface;
+	    char* src = (char*) sdesc.lpSurface;
+	    for (x = 0; x < width; x++)
+		for (y =0; y < height; y++) {
+		    DWORD pixel = 0;
+		    BYTE data[4];
+		    (*fetch_2d_texel_rgba_dxt1)(width, src, x, y, data);
+		    pixel = 0;
+		    pixel |= ((data[0] >> rb) << rs) & rm;
+		    pixel |= ((data[1] >> gb) << gs) & gm;
+		    pixel |= ((data[2] >> bb) << bs) & bm;
+		    pixel |= ((data[3] >> ab) << as) & am;
+		    if (is16)
+			*((WORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
+	            else
+			*((DWORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
+		}
+	} else if (sdesc.u4.ddpfPixelFormat.dwFourCC == MAKE_FOURCC('D','X','T','3')) {
+	    int is16 = ddesc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16;
+	    int pitch = ddesc.u1.lPitch;
+	    int width = ddesc.dwWidth;
+	    int height = ddesc.dwHeight;
+	    int x,y;
+	    char* dst = (char*) ddesc.lpSurface;
+	    char* src = (char*) sdesc.lpSurface;
+	    for (x = 0; x < width; x++)
+		for (y =0; y < height; y++) {
+		    DWORD pixel = 0;
+		    BYTE data[4];
+		    (*fetch_2d_texel_rgba_dxt3)(width, src, x, y, data);
+		    pixel = 0;
+		    pixel |= ((data[0] >> rb) << rs) & rm;
+		    pixel |= ((data[1] >> gb) << gs) & gm;
+		    pixel |= ((data[2] >> bb) << bs) & bm;
+		    pixel |= ((data[3] >> ab) << as) & am;
+                    if (is16)
+			*((WORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
+		    else
+			*((DWORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
+		}
+	} else if (sdesc.u4.ddpfPixelFormat.dwFourCC == MAKE_FOURCC('D','X','T','5')) {
+	    int is16 = ddesc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16;
+	    int pitch = ddesc.u1.lPitch;
+	    int width = ddesc.dwWidth;
+	    int height = ddesc.dwHeight;
+	    int x,y;
+	    char* dst = (char*) ddesc.lpSurface;
+	    char* src = (char*) sdesc.lpSurface;
+	    for (x = 0; x < width; x++)
+		for (y =0; y < height; y++) {
+		    DWORD pixel = 0;
+		    BYTE data[4];
+		    (*fetch_2d_texel_rgba_dxt5)(width, src, x, y, data);
+		    pixel = 0;
+		    pixel |= ((data[0] >> rb) << rs) & rm;
+		    pixel |= ((data[1] >> gb) << gs) & gm;
+		    pixel |= ((data[2] >> bb) << bs) & bm;
+		    pixel |= ((data[3] >> ab) << as) & am;
+		    if (is16)
+			*((WORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
+		    else
+			*((DWORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
+		}
+	}
+#if 0 /* Usefull for debugging */
+	{
+	  static int idx;
+	  char texname[255];
+	  FILE* f;
+	  sprintf(texname, "dxt_%d.pnm", idx++);
+	  f = fopen(texname,"w");
+	  DDRAW_dump_surface_to_disk(This, f, 1);
+	  fclose(f);
+	}
+#endif
+	goto release;
+    }
+    
     if (rdst) {
 	memcpy(&xdst,rdst,sizeof(xdst));
     } else {
@@ -842,6 +983,14 @@
     /* Get the surface description without locking to first compute the width / height */
     ddesc = This->surface_desc;
     sdesc = (ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src))->surface_desc;
+
+    if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) && (ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)) {
+	if (trans)
+	    FIXME("trans arg not supported when a FOURCC surface is involved\n");
+	if (dstx || dsty)
+	    FIXME("offset for destination surface is not supported\n");
+	DIB_DirectDrawSurface_Blt(iface, NULL, src, rsrc, 0, NULL);
+    }
     
     if (!rsrc) {
 	WARN("rsrc is NULL!\n");
Index: dsurface/main.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/main.c,v
retrieving revision 1.57
diff -u -r1.57 main.c
--- dsurface/main.c	4 Jun 2004 19:37:16 -0000	1.57
+++ dsurface/main.c	29 Jul 2004 21:46:14 -0000
@@ -1119,9 +1119,21 @@
 
 	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);
+	if (pDDSD->u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
+	    int blksize;
+	    switch(pDDSD->u4.ddpfPixelFormat.dwFourCC) {
+		case MAKE_FOURCC('D','X','T','1') : blksize = 8; break;
+		case MAKE_FOURCC('D','X','T','3') : blksize = 16; break;
+		case MAKE_FOURCC('D','X','T','5') : blksize = 16; break;
+		default: return DDERR_INVALIDPIXELFORMAT;
+	    }
+	    pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
+		+ prect->top/4 * (pDDSD->dwWidth+3)/4 * blksize
+	    	+ prect->left/4 * blksize;
+	} else
+	    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);
     }


More information about the wine-patches mailing list