Added native and emulated S3TC support.
diff --git a/configure b/configure
index b6eb400..69c9945 100755
--- a/configure
+++ b/configure
@@ -15272,6 +15272,80 @@
_ACEOF
fi
+echo "$as_me:$LINENO: checking for -ltxc_dxtn soname" >&5
+echo $ECHO_N "checking for -ltxc_dxtn soname... $ECHO_C" >&6
+if test "${ac_cv_lib_soname_txc_dxtn+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_get_soname_save_LIBS=$LIBS
+LIBS="-ltxc_dxtn $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char fetch_2d_texel_rgba_dxt1 ();
+int
+main ()
+{
+fetch_2d_texel_rgba_dxt1 ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_soname_txc_dxtn=`$ac_cv_path_LDD conftest$ac_exeext | grep libtxc_dxtn\\.$LIBEXT | sed "s/^.*\(libtxc_dxtn\.$LIBEXT[^ ]*\).*$/\1/"`
+ if test "x$ac_cv_lib_soname_txc_dxtn" = "x"
+ then
+ ac_cv_lib_soname_txc_dxtn="libtxc_dxtn.$LIBEXT"
+ fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_soname_txc_dxtn="libtxc_dxtn.$LIBEXT"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_get_soname_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_soname_txc_dxtn" >&5
+echo "${ECHO_T}$ac_cv_lib_soname_txc_dxtn" >&6
+if test "x$ac_cv_lib_soname_txc_dxtn" != xNONE
+then
+cat >>confdefs.h <<_ACEOF
+#define SONAME_LIBTXC_DXTN "$ac_cv_lib_soname_txc_dxtn"
+_ACEOF
+fi
+
echo "$as_me:$LINENO: checking for -lcups soname" >&5
echo $ECHO_N "checking for -lcups soname... $ECHO_C" >&6
if test "${ac_cv_lib_soname_cups+set}" = set; then
diff --git a/configure.ac b/configure.ac
index 5fa645d..e9e4df8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1023,6 +1023,7 @@
WINE_GET_SONAME(Xrandr,XRRQueryExtension,[$X_LIBS -lXext -lX11 $X_EXTRA_LIBS])
WINE_GET_SONAME(freetype,FT_Init_FreeType,[$X_LIBS])
WINE_GET_SONAME(GL,glXQueryExtension,[$X_LIBS $X_EXTRA_LIBS])
+ WINE_GET_SONAME(txc_dxtn,fetch_2d_texel_rgba_dxt1)
WINE_GET_SONAME(cups,cupsGetDefault)
WINE_GET_SONAME(jack,jack_client_new)
WINE_GET_SONAME(fontconfig,FcInit)
diff --git a/dlls/ddraw/d3d_private.h b/dlls/ddraw/d3d_private.h
index 37b10b2..fcafc4b 100644
--- a/dlls/ddraw/d3d_private.h
+++ b/dlls/ddraw/d3d_private.h
@@ -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 */
diff --git a/dlls/ddraw/d3ddevice/mesa.c b/dlls/ddraw/d3ddevice/mesa.c
index 11b5a59..4b21b2f 100644
--- a/dlls/ddraw/d3ddevice/mesa.c
+++ b/dlls/ddraw/d3ddevice/mesa.c
@@ -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;
}
@@ -4236,6 +4256,13 @@
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");
+ }
}
/* Fill the D3D capabilities according to what GL tells us... */
diff --git a/dlls/ddraw/d3dtexture.c b/dlls/ddraw/d3dtexture.c
index 464a1d2..ffe068e 100644
--- a/dlls/ddraw/d3dtexture.c
+++ b/dlls/ddraw/d3dtexture.c
@@ -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... */
diff --git a/dlls/ddraw/ddraw/main.c b/dlls/ddraw/ddraw/main.c
index b3625fc..80d0df4 100644
--- a/dlls/ddraw/ddraw/main.c
+++ b/dlls/ddraw/ddraw/main.c
@@ -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);
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 26669d2..b7915ef 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -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)
diff --git a/dlls/ddraw/dsurface/dib.c b/dlls/ddraw/dsurface/dib.c
index 5aaac53..eedcbcc 100644
--- a/dlls/ddraw/dsurface/dib.c
+++ b/dlls/ddraw/dsurface/dib.c
@@ -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");
diff --git a/dlls/ddraw/dsurface/main.c b/dlls/ddraw/dsurface/main.c
index 6631190..f4d26f5 100644
--- a/dlls/ddraw/dsurface/main.c
+++ b/dlls/ddraw/dsurface/main.c
@@ -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);
}
diff --git a/dlls/ddraw/main.c b/dlls/ddraw/main.c
index 50b3eff..7c149c7 100644
--- a/dlls/ddraw/main.c
+++ b/dlls/ddraw/main.c
@@ -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_LIBTXC_DXTN
+#define SONAME_LIBTXC_DXTN "libtxc_dxtn.so"
+#endif
+
+static BOOL DDRAW_bind_to_s3tc( void )
+{
+ const char * const s3tcname = SONAME_LIBTXC_DXTN;
+
+ 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)
diff --git a/dlls/ddraw/mesa.c b/dlls/ddraw/mesa.c
index 8bb1934..af5affe 100644
--- a/dlls/ddraw/mesa.c
+++ b/dlls/ddraw/mesa.c
@@ -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);
diff --git a/dlls/ddraw/mesa_private.h b/dlls/ddraw/mesa_private.h
index cfa36c4..0a5b346 100644
--- a/dlls/ddraw/mesa_private.h
+++ b/dlls/ddraw/mesa_private.h
@@ -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;
diff --git a/include/config.h.in b/include/config.h.in
index feb1905..d15ecae 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -893,6 +893,9 @@
/* Define to the soname of the libssl library. */
#undef SONAME_LIBSSL
+/* Define to the soname of the libtxc_dxtn library. */
+#undef SONAME_LIBTXC_DXTN
+
/* Define to the soname of the libX11 library. */
#undef SONAME_LIBX11