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