[D3D] Add S3TC support to BltFast

Lionel Ulmer lionel.ulmer at free.fr
Sat Jul 31 08:48:35 CDT 2004


Christian,

You will be able to check if I did not introduce any regression on your test
applications :-)

            Lionel

Changelog:
 - add S3TC support to BltFast (fixes NOLF)
 - proper surface unlocking in case of error in the Blt case

-- 
		 Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
Index: dlls/ddraw/dsurface/dib.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/dib.c,v
retrieving revision 1.36
diff -u -r1.36 dib.c
--- dlls/ddraw/dsurface/dib.c	30 Jul 2004 18:54:32 -0000	1.36
+++ dlls/ddraw/dsurface/dib.c	31 Jul 2004 13:45:49 -0000
@@ -359,26 +359,132 @@
     return DD_OK;
 }
 
-void ComputeShifts(DWORD mask, DWORD* lshift, DWORD* rshift)
+static 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++;
+    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;
+}
 
-  *lshift = pos;
-  *rshift = 8 - bits;
+/* This is used to factorize the decompression between the Blt and BltFast code */
+static void DoDXTCDecompression(const DDSURFACEDESC2 *sdesc, const DDSURFACEDESC2 *ddesc)
+{
+    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");
+	return;
+    }
+    
+    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
 }
-  
+
 HRESULT WINAPI
 DIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst,
 			  LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
@@ -391,7 +497,7 @@
     int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
     int x, y;
     LPBYTE dbuf, sbuf;
-
+    
     TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
 
     if (TRACE_ON(ddraw)) {
@@ -422,7 +528,8 @@
 	(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;
+	    ret = DDERR_INVALIDPIXELFORMAT;
+	    goto release;
 	}
 	memcpy(ddesc.lpSurface, sdesc.lpSurface, ddesc.u1.dwLinearSize);
 	goto release;
@@ -430,107 +537,7 @@
 
     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
+	DoDXTCDecompression(&sdesc, &ddesc);
 	goto release;
     }
     
@@ -984,14 +991,6 @@
     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");
 	rsrc = &rsrc2;
@@ -1027,6 +1026,26 @@
     ddesc.dwSize = sizeof(ddesc);
     IDirectDrawSurface7_Lock(iface, &lock_dst, &ddesc, DDLOCK_WRITEONLY, 0);
 
+    /* Handle first the FOURCC surfaces... */
+    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");
+	if (sdesc.u4.ddpfPixelFormat.dwFourCC != sdesc.u4.ddpfPixelFormat.dwFourCC) {
+	    FIXME("FOURCC->FOURCC copy only supported for the same type of surface\n");
+	    ret = DDERR_INVALIDPIXELFORMAT;
+	    goto error;
+	}
+	memcpy(ddesc.lpSurface, sdesc.lpSurface, ddesc.u1.dwLinearSize);
+	goto error;
+    }
+    if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
+	(!(ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC))) {
+	DoDXTCDecompression(&sdesc, &ddesc);
+	goto error;
+    }
+    
     bpp = GET_BPP(This->surface_desc);
     sbuf = (BYTE *) sdesc.lpSurface;
     dbuf = (BYTE *) ddesc.lpSurface;


More information about the wine-patches mailing list