[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