[D3D] Added native and emulated S3TC support

Christian Costa titan.costa at wanadoo.fr
Tue Jul 27 14:05:13 CDT 2004


Hi,

The title says it all.
For the emulated S3TC support, the DXT (de)compression library from the
DRI project is used.
(I attached the sources). Just compile it and install it.
Native support has a small problem with mipmapping...

Tested with Earthworm Jim 3D.

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	26 Jul 2004 20:38:29 -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	26 Jul 2004 20:38:31 -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	26 Jul 2004 20:38:32 -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
  */
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	26 Jul 2004 20:38:33 -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,48 @@
 
 #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) {
+        printf("Wine cannot find the S3TC software decompression library (%s).\n",s3tcname);
+	return FALSE;
+    }
+
+#define API_FUNCTION(f)  \
+    if((f = wine_dlsym(s3tc_handle, #f, NULL, 0)) == NULL) \
+    { \
+        printf("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 decompression\n");
+    wine_dlclose(s3tc_handle, NULL, 0);
+    s3tc_handle = NULL;
+    return FALSE;
+}
+
 /***********************************************************************
  *		DirectDrawEnumerateExA (DDRAW.@)
  */
@@ -607,6 +644,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	26 Jul 2004 20:38:36 -0000
@@ -654,6 +654,27 @@
     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;
+	}
+	GL_extensions.glCompressedTexImage2D(GL_TEXTURE_2D, current_level, retVal, width, height, 0, size, buffer);
+
+	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 +953,28 @@
     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;
+	}
+	/* 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);
+
+	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	26 Jul 2004 20:38:36 -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	26 Jul 2004 20:38:46 -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	26 Jul 2004 20:38:49 -0000
@@ -380,16 +380,30 @@
 	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;
     }
     
     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 +447,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	26 Jul 2004 20:38:53 -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,114 @@
     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;
+	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 +975,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	26 Jul 2004 20:38:55 -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);
     }

-------------- next part --------------
A non-text attachment was scrubbed...
Name: libtxc_dxtn040524.tar.gz
Type: application/x-tar
Size: 9658 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-patches/attachments/20040727/eb15ae62/libtxc_dxtn040524.tar.tar


More information about the wine-patches mailing list