- added definition of DirectDrawCreateClipper.
- more versatile support of surfaces / better surface description support.

diff --git a/graphics/ddraw.c b/graphics/ddraw.c
index 3a9d787..1969b44 100644
--- a/graphics/ddraw.c
+++ b/graphics/ddraw.c
@@ -282,6 +282,42 @@
 	DUMP("\n");
 }
 
+static void _dump_DDCOLORKEY(DWORD flagmask) {
+	int	i;
+	const struct {
+		DWORD	mask;
+		char	*name;
+	} flags[] = {
+#define FE(x) { x, #x},
+	        FE(DDPF_ALPHAPIXELS)
+		FE(DDPF_ALPHA)
+		FE(DDPF_FOURCC)
+		FE(DDPF_PALETTEINDEXED4)
+		FE(DDPF_PALETTEINDEXEDTO8)
+		FE(DDPF_PALETTEINDEXED8)
+		FE(DDPF_RGB)
+		FE(DDPF_COMPRESSED)
+		FE(DDPF_RGBTOYUV)
+		FE(DDPF_YUV)
+		FE(DDPF_ZBUFFER)
+		FE(DDPF_PALETTEINDEXED1)
+		FE(DDPF_PALETTEINDEXED2)
+		FE(DDPF_ZPIXELS)
+	};
+	for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+		if (flags[i].mask & flagmask)
+			DUMP("%s ",flags[i].name);
+	DUMP("\n");
+}
+
+static void _dump_pixelformat(LPDDPIXELFORMAT pf) {
+  _dump_DDCOLORKEY(pf->dwFlags);
+  DUMP("dwFourCC : %ld\n", pf->dwFourCC);
+  DUMP("RBG bit cbout : %ld\n", pf->x.dwRGBBitCount);
+  DUMP("Masks : R %08lx  G %08lx  B %08lx  A %08lx\n",
+       pf->y.dwRBitMask, pf->z.dwGBitMask, pf->xx.dwBBitMask, pf->xy.dwRGBAlphaBitMask);
+}
+
 static int _getpixelformat(LPDIRECTDRAW2 ddraw,LPDDPIXELFORMAT pf) {
 	static XVisualInfo	*vi;
 	XVisualInfo		vt;
@@ -329,22 +365,20 @@
 	    WARN(ddraw, "(%p)->Lock(%p,%p,%08lx,%08lx)\n",
 			 this,lprect,lpddsd,flags,(DWORD)hnd);
 
+	/* First, copy the Surface description */
+	*lpddsd = this->s.surface_desc;
+
+	/* If asked only for a part, change the surface pointer */
 	if (lprect) {
 		FIXME(ddraw,"	lprect: %dx%d-%dx%d\n",
 			lprect->top,lprect->left,lprect->bottom,lprect->right
 		);
-		lpddsd->y.lpSurface = this->s.surface +
-			(lprect->top*this->s.lpitch) +
-			(lprect->left*(this->s.ddraw->d.depth/8));
+		lpddsd->y.lpSurface = this->s.surface_desc.y.lpSurface +
+			(lprect->top*this->s.surface_desc.lPitch) +
+			(lprect->left*(this->s.surface_desc.ddpfPixelFormat.x.dwRGBBitCount / 8));
 	} else {
-		assert(this->s.surface);
-		lpddsd->y.lpSurface = this->s.surface;
+		assert(this->s.surface_desc.y.lpSurface);
 	}
-	lpddsd->dwFlags = DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_LPSURFACE;
-	lpddsd->dwWidth		= this->s.width;
-	lpddsd->dwHeight	= this->s.height;
-	lpddsd->lPitch		= this->s.lpitch;
-	_getpixelformat(this->s.ddraw,&(lpddsd->ddpfPixelFormat));
 	return 0;
 }
 
@@ -364,7 +398,8 @@
 		return DD_OK;
 
   /* Only redraw the screen when unlocking the buffer that is on screen */
-  if ((this->t.xlib.image != NULL) && (this->t.xlib.on_screen)) {
+	if ((this->t.xlib.image != NULL) &&
+	    (this->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_VISIBLE)) {
 #ifdef HAVE_LIBXXSHM
     if (this->s.ddraw->e.xlib.xshm_active)
       TSXShmPutImage(display,
@@ -384,10 +419,10 @@
 				0, 0, 0, 0,
 				this->t.xlib.image->width,
 		  this->t.xlib.image->height);
-  }
   
 	if (this->s.palette && this->s.palette->cm)
 		TSXSetWindowColormap(display,this->s.ddraw->e.xlib.drawable,this->s.palette->cm);
+	}
 
 	return DD_OK;
 }
@@ -418,9 +453,9 @@
 		this->t.dga.fb_height = flipto->t.dga.fb_height;
 		flipto->t.dga.fb_height = tmp;
 
-		ptmp = this->s.surface;
-		this->s.surface = flipto->s.surface;
-		flipto->s.surface = ptmp;
+		ptmp = this->s.surface_desc.y.lpSurface;
+		this->s.surface_desc.y.lpSurface = flipto->s.surface_desc.y.lpSurface;
+		flipto->s.surface_desc.y.lpSurface = ptmp;
 	}
 	return 0;
 #else /* defined(HAVE_LIBXXF86DGA) */
@@ -471,9 +506,9 @@
 		tmp = this->t.xlib.image;
 		this->t.xlib.image = flipto->t.xlib.image;
 		flipto->t.xlib.image = tmp;
-		surf = this->s.surface;
-		this->s.surface = flipto->s.surface;
-		flipto->s.surface = surf;
+		surf = this->s.surface_desc.y.lpSurface;
+		this->s.surface_desc.y.lpSurface = flipto->s.surface_desc.y.lpSurface;
+		flipto->s.surface_desc.y.lpSurface = surf;
 	}
 	return 0;
 }
@@ -552,11 +587,17 @@
 	LPDIRECTDRAWSURFACE3 this,LPRECT32 rdst,LPDIRECTDRAWSURFACE3 src,LPRECT32 rsrc,DWORD dwFlags,LPDDBLTFX lpbltfx
 ) {
 	RECT32	xdst,xsrc;
+	DDSURFACEDESC	ddesc,sdesc;
 	int	i,j;
 
-	if (TRACE_ON(ddraw)) {
 	  TRACE(ddraw,"(%p)->(%p,%p,%p,%08lx,%p)\n",
 		this,rdst,src,rsrc,dwFlags,lpbltfx);
+
+	if (src != NULL)
+	  src ->lpvtbl->fnLock(src, NULL,&sdesc,0,0);
+	this->lpvtbl->fnLock(this,NULL,&ddesc,0,0);
+	
+	if (TRACE_ON(ddraw)) {
 	  if (rdst) TRACE(ddraw,"	destrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
 	  if (rsrc) TRACE(ddraw,"	srcrect  :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
 	  TRACE(ddraw,"\tflags: ");_dump_DDBLT(dwFlags);fprintf(stderr,"\n");
@@ -569,9 +610,9 @@
 		memcpy(&xdst,rdst,sizeof(xdst));
 	} else {
 		xdst.top	= 0;
-		xdst.bottom	= this->s.height;
+		xdst.bottom	= ddesc.dwHeight;
 		xdst.left	= 0;
-		xdst.right	= this->s.width;
+		xdst.right	= ddesc.dwWidth;
 	}
 
 	if (rsrc) {
@@ -579,9 +620,9 @@
 	} else {
 		if (src) {
 		xsrc.top	= 0;
-		xsrc.bottom	= src->s.height;
+		xsrc.bottom	= sdesc.dwHeight;
 		xsrc.left	= 0;
-		xsrc.right	= src->s.width;
+		xsrc.right	= sdesc.dwWidth;
 		} else {
 		    memset(&xsrc,0,sizeof(xsrc));
 		}
@@ -590,10 +631,10 @@
 	dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
 	
 	if (dwFlags & DDBLT_COLORFILL) {
-		int	bpp = this->s.ddraw->d.depth/8;
+		int	bpp = ddesc.ddpfPixelFormat.x.dwRGBBitCount / 8;
 		LPBYTE	xline,xpixel;
 
-		xline = (LPBYTE)this->s.surface+xdst.top*this->s.lpitch;
+		xline = (LPBYTE) ddesc.y.lpSurface + xdst.top * ddesc.lPitch;
 		for (i=xdst.top;i<xdst.bottom;i++) {
 			xpixel = xline+bpp*xdst.left;
 
@@ -605,7 +646,7 @@
 				memcpy(xpixel,&(lpbltfx->b.dwFillColor),bpp);
 				xpixel += bpp;
 			}
-			xline += this->s.lpitch;
+			xline += ddesc.lPitch;
 		}
 		dwFlags &= ~(DDBLT_COLORFILL);
 	}
@@ -617,22 +658,24 @@
 	    return 0;
 	}
 
-	if (	(xsrc.top ==0) && (xsrc.bottom ==this->s.height) &&
-		(xsrc.left==0) && (xsrc.right  ==this->s.width) &&
-		(xdst.top ==0) && (xdst.bottom ==this->s.height) &&
-		(xdst.left==0) && (xdst.right  ==this->s.width)  &&
+	if (	(xsrc.top ==0) && (xsrc.bottom ==ddesc.dwHeight) &&
+		(xsrc.left==0) && (xsrc.right  ==ddesc.dwWidth) &&
+		(xdst.top ==0) && (xdst.bottom ==ddesc.dwHeight) &&
+		(xdst.left==0) && (xdst.right  ==ddesc.dwWidth)  &&
 		!dwFlags
 	) {
-		memcpy(this->s.surface,src->s.surface,this->s.height*this->s.lpitch);
+		memcpy(ddesc.y.lpSurface,
+		       sdesc.y.lpSurface,
+		       ddesc.dwHeight * ddesc.lPitch);
 	} else {
-	  int bpp = this->s.ddraw->d.depth / 8;
+	  int bpp = ddesc.ddpfPixelFormat.x.dwRGBBitCount / 8;
 	  int height = xsrc.bottom - xsrc.top;
 	  int width = (xsrc.right - xsrc.left) * bpp;
 	  int h;
 
 	  for (h = 0; h < height; h++) {
-	    memcpy(this->s.surface + ((h + xdst.top) * this->s.lpitch) + xdst.left * bpp,
-		   src->s.surface + ((h + xsrc.top) * src->s.lpitch) + xsrc.left * bpp,
+	    memcpy(ddesc.y.lpSurface + ((h + xdst.top) * ddesc.lPitch) + xdst.left * bpp,
+		   sdesc.y.lpSurface + ((h + xsrc.top) * sdesc.lPitch) + xsrc.left * bpp,
 		   width);
 	  }
 	}
@@ -640,48 +683,13 @@
 	if (dwFlags && FIXME_ON(ddraw)) {
 	  FIXME(ddraw,"\tUnsupported flags: ");_dump_DDBLT(dwFlags);
 	}
+
+	this->lpvtbl->fnUnlock(this,ddesc.y.lpSurface);
+	src ->lpvtbl->fnUnlock(src,sdesc.y.lpSurface);
+
 	return 0;
 }
 
-static HRESULT WINAPI Xlib_IDirectDrawSurface3_Blt(
-	LPDIRECTDRAWSURFACE3 this,LPRECT32 rdst,LPDIRECTDRAWSURFACE3 src,LPRECT32 rsrc,DWORD dwFlags,LPDDBLTFX lpbltfx
-) {
-  HRESULT ret;
-  
-  /* First, call the "common" blit function */
-  ret = IDirectDrawSurface3_Blt(this, rdst, src, rsrc, dwFlags, lpbltfx);
-
-  /* Then put the result on screen if blited on main screen buffer */
-  if (!this->s.ddraw->e.xlib.paintable)
-    return ret;
-
-  if ((this->t.xlib.image != NULL) && (this->t.xlib.on_screen)) {
-#ifdef HAVE_LIBXXSHM
-    if (this->s.ddraw->e.xlib.xshm_active)
-      TSXShmPutImage(display,
-		     this->s.ddraw->e.xlib.drawable,
-		     DefaultGCOfScreen(screen),
-		     this->t.xlib.image,
-		     0, 0, 0, 0,
-		     this->t.xlib.image->width,
-		     this->t.xlib.image->height,
-		     False);
-    else
-#endif
-      TSXPutImage(display,
-		  this->s.ddraw->e.xlib.drawable,
-		  DefaultGCOfScreen(screen),
-		  this->t.xlib.image,
-		  0, 0, 0, 0,
-		  this->t.xlib.image->width,
-		  this->t.xlib.image->height);
-  }
-  if (this->s.palette && this->s.palette->cm)
-    TSXSetWindowColormap(display,this->s.ddraw->e.xlib.drawable,this->s.palette->cm);
-
-  return ret;
-}
-
 static HRESULT WINAPI IDirectDrawSurface3_BltFast(
 	LPDIRECTDRAWSURFACE3 this,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE3 src,LPRECT32 rsrc,DWORD trans
 ) {
@@ -698,7 +706,7 @@
 	/* We need to lock the surfaces, or we won't get refreshes when done */
 	src ->lpvtbl->fnLock(src, NULL,&sdesc,0,0);
 	this->lpvtbl->fnLock(this,NULL,&ddesc,0,0);
-	bpp = this->s.ddraw->d.depth/8;
+	bpp = this->s.surface_desc.ddpfPixelFormat.x.dwRGBBitCount / 8;
 	for (i=0;i<rsrc->bottom-rsrc->top;i++) {
 		memcpy(	ddesc.y.lpSurface+(dsty     +i)*ddesc.lPitch+dstx*bpp,
 			sdesc.y.lpSurface+(rsrc->top+i)*sdesc.lPitch+rsrc->left*bpp,
@@ -730,24 +738,22 @@
 static HRESULT WINAPI IDirectDrawSurface3_GetSurfaceDesc(
 	LPDIRECTDRAWSURFACE3 this,LPDDSURFACEDESC ddsd
 ) { 
-	if (TRACE_ON(ddraw)) {
 		TRACE(ddraw, "(%p)->GetSurfaceDesc(%p)\n",
 			     this,ddsd);
+  
+  /* Simply copy the surface description stored in the object */
+  *ddsd = this->s.surface_desc;
+  
+  if (TRACE_ON(ddraw)) {
 		fprintf(stderr,"	flags: ");
 		_dump_DDSD(ddsd->dwFlags);
+    if (ddsd->dwFlags & DDSD_CAPS) {
+      fprintf(stderr, "  caps:  ");
+      _dump_DDSCAPS(ddsd->ddsCaps.dwCaps);
+    }
 		fprintf(stderr,"\n");
 	}
 
-	ddsd->dwFlags |= DDSD_PIXELFORMAT|DDSD_CAPS|DDSD_BACKBUFFERCOUNT|DDSD_HEIGHT|DDSD_WIDTH;
-	ddsd->ddsCaps.dwCaps	= DDSCAPS_PALETTE;
-	ddsd->dwBackBufferCount	= 1;
-	ddsd->dwHeight		= this->s.height;
-	ddsd->dwWidth		= this->s.width;
-	ddsd->lPitch		= this->s.lpitch;
-	if (this->s.backbuffer)
-		ddsd->ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP;
-	_getpixelformat(this->s.ddraw,&(ddsd->ddpfPixelFormat));
-	
 	return 0;
 }
 
@@ -765,7 +771,7 @@
 		this->s.ddraw->lpvtbl->fnRelease(this->s.ddraw);
 		/* clear out of surface list */
 		if (this->t.dga.fb_height == -1) {
-			HeapFree(GetProcessHeap(),0,this->s.surface);
+			HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
 		} else {
 			this->s.ddraw->e.dga.vpmask &= ~(1<<(this->t.dga.fb_height/this->s.ddraw->e.dga.fb_height));
 		}
@@ -795,7 +801,7 @@
 	shmdt(this->t.xlib.shminfo.shmaddr);
       } else {
 #endif
-	HeapFree(GetProcessHeap(),0,this->s.surface);
+	      HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
 	TSXDestroyImage(this->t.xlib.image);
 #ifdef HAVE_LIBXXSHM	
       }
@@ -803,7 +809,7 @@
       
 		this->t.xlib.image = 0;
     } else {
-      HeapFree(GetProcessHeap(),0,this->s.surface);
+	    HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
     }
 
 		if (this->s.palette)
@@ -844,6 +850,8 @@
 static HRESULT WINAPI IDirectDrawSurface3_Initialize(
 	LPDIRECTDRAWSURFACE3 this,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd
 ) {
+	TRACE(ddraw,"(%p)->(%p, %p)\n",this,ddraw,lpdsfd);
+
 	return DDERR_ALREADYINITIALIZED;
 }
 
@@ -851,7 +859,10 @@
 	LPDIRECTDRAWSURFACE3 this,LPDDPIXELFORMAT pf
 ) {
 	TRACE(ddraw,"(%p)->(%p)\n",this,pf);
-	return _getpixelformat(this->s.ddraw,pf);
+
+	*pf = this->s.surface_desc.ddpfPixelFormat;
+	
+	return 0;
 }
 
 static HRESULT WINAPI IDirectDrawSurface3_GetBltStatus(LPDIRECTDRAWSURFACE3 this,DWORD dwFlags) {
@@ -877,6 +888,9 @@
 	LPDIRECTDRAWSURFACE3 this,LPDIRECTDRAWSURFACE3 surf
 ) {
 	FIXME(ddraw,"(%p)->(%p),stub!\n",this,surf);
+
+	/* This hack will be enough for the moment */
+	if (this->s.backbuffer == NULL)
 	this->s.backbuffer = surf;
 	return 0;
 }
@@ -1140,7 +1154,7 @@
 	Xlib_IDirectDrawSurface3_Release,
 	IDirectDrawSurface3_AddAttachedSurface,
 	IDirectDrawSurface3_AddOverlayDirtyRect,
-	Xlib_IDirectDrawSurface3_Blt,
+	IDirectDrawSurface3_Blt,
 	IDirectDrawSurface3_BltBatch,
 	IDirectDrawSurface3_BltFast,
 	IDirectDrawSurface3_DeleteAttachedSurface,
@@ -1177,6 +1191,21 @@
 	IDirectDrawSurface3_SetSurfaceDesc,
 };
 
+/******************************************************************************
+ *			DirectDrawCreateClipper (DDRAW.7)
+ */
+HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags,
+				        LPDIRECTDRAWCLIPPER *lplpDDClipper,
+				        LPUNKNOWN pUnkOuter)
+{
+  TRACE(ddraw, "(%08lx,%p,%p)\n", dwFlags, lplpDDClipper, pUnkOuter);
+
+  *lplpDDClipper = (LPDIRECTDRAWCLIPPER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipper));
+  (*lplpDDClipper)->lpvtbl = &ddclipvt;
+  (*lplpDDClipper)->ref = 1;
+
+  return 0;
+}
 
 /******************************************************************************
  *			IDirectDrawClipper
@@ -1233,6 +1262,9 @@
 ) {
 	int	i;
 
+	TRACE(ddraw,"(%p)->GetEntries(%08lx,%ld,%ld,%p)\n",
+	      this,x,start,count,palent);
+
 	if (!this->cm) /* should not happen */ {
 		FIXME(ddraw,"app tried to read colormap for non-palettized mode\n");
 		return DDERR_GENERIC;
@@ -1342,6 +1374,8 @@
 static HRESULT WINAPI IDirectDrawPalette_Initialize(
 	LPDIRECTDRAWPALETTE this,LPDIRECTDRAW ddraw,DWORD x,LPPALETTEENTRY palent
 ) {
+        TRACE(ddraw,"(%p)->(%p,%ld,%p)\n", this, ddraw, x, palent);
+
 	return DDERR_ALREADYINITIALIZED;
 }
 
@@ -1383,6 +1417,9 @@
 	Xlib_IDirectDrawPalette_SetEntries
 };
 
+/*******************************************************************************
+ *				IDirect3D
+ */
 static HRESULT WINAPI IDirect3D_QueryInterface(
         LPDIRECT3D this,REFIID refiid,LPVOID *obj
 ) {
@@ -1519,6 +1556,38 @@
  */
 static INT32 ddrawXlibThisOffset = 0;
 
+static HRESULT common_off_screen_CreateSurface(LPDIRECTDRAW2 this,
+					       LPDDSURFACEDESC lpddsd,
+					       LPDIRECTDRAWSURFACE lpdsf)
+{
+  int bpp;
+  
+  /* The surface was already allocated when entering in this function */
+  if (!(lpddsd->dwFlags & DDSD_PIXELFORMAT)) {
+    /* No pixel format => use DirectDraw's format */
+    _getpixelformat(this,&(lpddsd->ddpfPixelFormat));
+    lpddsd->dwFlags |= DDSD_PIXELFORMAT;
+  }  else {
+    /* To check what the program wants */
+    if (TRACE_ON(ddraw)) {
+      _dump_pixelformat(&(lpddsd->ddpfPixelFormat));
+    }
+  }
+
+  bpp = lpddsd->ddpfPixelFormat.x.dwRGBBitCount / 8;
+
+  /* Copy the surface description */
+  lpdsf->s.surface_desc = *lpddsd;
+  
+  lpdsf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE;
+  lpdsf->s.surface_desc.y.lpSurface = (LPBYTE)HeapAlloc(GetProcessHeap(),0,lpddsd->dwWidth * lpddsd->dwHeight * bpp);
+  lpdsf->s.surface_desc.lPitch = lpddsd->dwWidth * bpp;
+  
+  TRACE(ddraw,"using system memory for a surface (%p)\n", lpdsf);
+
+  return 0;
+}
+
 static HRESULT WINAPI DGA_IDirectDraw2_CreateSurface(
 	LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
 ) {
@@ -1538,42 +1607,52 @@
 	this->lpvtbl->fnAddRef(this);
 	(*lpdsf)->ref = 1;
 	(*lpdsf)->lpvtbl = (LPDIRECTDRAWSURFACE_VTABLE)&dga_dds3vt;
-	if (	(lpddsd->dwFlags & DDSD_CAPS) && 
-		(lpddsd->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
-	) {
+	(*lpdsf)->s.ddraw = this;
+	(*lpdsf)->s.palette = NULL;
+	(*lpdsf)->t.dga.fb_height = -1; /* This is to have non-on screen surfaces freed */
+
 		if (!(lpddsd->dwFlags & DDSD_WIDTH))
-			lpddsd->dwWidth = this->e.dga.fb_width;
+	  lpddsd->dwWidth  = this->d.width;
 		if (!(lpddsd->dwFlags & DDSD_HEIGHT))
-			lpddsd->dwHeight = this->e.dga.fb_height;
-		(*lpdsf)->s.surface = (LPBYTE)HeapAlloc(GetProcessHeap(),0,lpddsd->dwWidth*lpddsd->dwHeight*this->d.depth/8);
-		(*lpdsf)->t.dga.fb_height = -1;
-		(*lpdsf)->s.lpitch = lpddsd->dwWidth*this->d.depth/8;
-		TRACE(ddraw,"using system memory for a primary surface\n");
-	} else {
+	  lpddsd->dwHeight = this->d.height;
+	
+	/* Check if this a 'primary surface' or not */
+	if ((lpddsd->dwFlags & DDSD_CAPS) &&
+	    (lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {
+
+	  /* This is THE primary surface => there is DGA-specific code */
+	  /* First, store the surface description */
+	  (*lpdsf)->s.surface_desc = *lpddsd;
+	  
+	  /* Find a viewport */
 		for (i=0;i<32;i++)
 			if (!(this->e.dga.vpmask & (1<<i)))
 				break;
 		TRACE(ddraw,"using viewport %d for a primary surface\n",i);
 		/* if i == 32 or maximum ... return error */
 		this->e.dga.vpmask|=(1<<i);
-		(*lpdsf)->s.surface = this->e.dga.fb_addr+((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.depth/8);
+	  (*lpdsf)->s.surface_desc.y.lpSurface =
+	    this->e.dga.fb_addr+((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.depth/8);
 		(*lpdsf)->t.dga.fb_height = i*this->e.dga.fb_height;
-		(*lpdsf)->s.lpitch = this->e.dga.fb_width*this->d.depth/8;
-	}
+	  (*lpdsf)->s.surface_desc.lPitch = this->e.dga.fb_width*this->d.depth/8;
+	  lpddsd->lPitch = (*lpdsf)->s.surface_desc.lPitch;
 
-	lpddsd->lPitch = (*lpdsf)->s.lpitch;
-
-	(*lpdsf)->s.width = this->d.width;
-	(*lpdsf)->s.height = this->d.height;
-	(*lpdsf)->s.ddraw = this;
+	  /* Add flags if there were not present */
+	  (*lpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE;
+	  (*lpdsf)->s.surface_desc.dwWidth = this->d.width;
+	  (*lpdsf)->s.surface_desc.dwHeight = this->d.height;
+	  (*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
+	  _getpixelformat(this,&((*lpdsf)->s.surface_desc.ddpfPixelFormat));
 	(*lpdsf)->s.backbuffer = NULL;
+	  
 	if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
 		LPDIRECTDRAWSURFACE3	back;
 
 		if (lpddsd->dwBackBufferCount>1)
 			FIXME(ddraw,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
 
-		(*lpdsf)->s.backbuffer = back = (LPDIRECTDRAWSURFACE3)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface3));
+	    (*lpdsf)->s.backbuffer = back =
+	      (LPDIRECTDRAWSURFACE3)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface3));
 		this->lpvtbl->fnAddRef(this);
 		back->ref = 1;
 		back->lpvtbl = (LPDIRECTDRAWSURFACE3_VTABLE)&dga_dds3vt;
@@ -1583,16 +1662,29 @@
 		TRACE(ddraw,"using viewport %d for backbuffer\n",i);
 		/* if i == 32 or maximum ... return error */
 		this->e.dga.vpmask|=(1<<i);
-		back->s.surface = this->e.dga.fb_addr+((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.depth/8);
 		back->t.dga.fb_height = i*this->e.dga.fb_height;
 
-		back->s.width = this->d.width;
-		back->s.height = this->d.height;
+	    /* Copy the surface description from the front buffer */
+	    back->s.surface_desc = (*lpdsf)->s.surface_desc;
+	    /* Change the parameters that are not the same */
+	    back->s.surface_desc.y.lpSurface = this->e.dga.fb_addr+
+	      ((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.depth/8);
 		back->s.ddraw = this;
-		back->s.lpitch = this->e.dga.fb_width*this->d.depth/8;
 		back->s.backbuffer = NULL; /* does not have a backbuffer, it is
 					    * one! */
+
+	    /* Add relevant info to front and back buffers */
+	    (*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
+	    back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
+	    back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
+	    back->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
+	  }
+	} else {
+	  /* There is no DGA-specific code here...
+	     Go to the common surface creation function */
+	  return common_off_screen_CreateSurface(this, lpddsd, *lpdsf);
 	}
+	
 	return 0;
 #else /* defined(HAVE_LIBXXF86DGA) */
 	return E_UNEXPECTED;
@@ -1610,8 +1702,8 @@
 			    ZPixmap,
 			    NULL,
 			    &(lpdsf->t.xlib.shminfo),
-			    lpdsf->s.width,
-			    lpdsf->s.height);
+			    lpdsf->s.surface_desc.dwWidth,
+			    lpdsf->s.surface_desc.dwHeight);
     
     if (img == NULL)
       return NULL;
@@ -1636,11 +1728,14 @@
 
     shmctl(lpdsf->t.xlib.shminfo.shmid, IPC_RMID, 0);
 
-    lpdsf->s.surface = img->data;
+    lpdsf->s.surface_desc.y.lpSurface = img->data;
   } else {
 #endif
     /* Allocate surface memory */
-    lpdsf->s.surface = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpdsf->s.width * lpdsf->s.height *this->d.depth/8);
+    lpdsf->s.surface_desc.y.lpSurface = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
+						  lpdsf->s.surface_desc.dwWidth *
+						  lpdsf->s.surface_desc.dwHeight *
+						  (this->d.depth / 8));
     
     /* In this case, create an XImage */
     img =
@@ -1649,17 +1744,17 @@
 		     this->d.depth,
 		     ZPixmap,
 		     0,
-		     lpdsf->s.surface,
-		     lpdsf->s.width,
-		     lpdsf->s.height,
+		     lpdsf->s.surface_desc.y.lpSurface,
+		     lpdsf->s.surface_desc.dwWidth,
+		     lpdsf->s.surface_desc.dwHeight,
 		     32,
-		     lpdsf->s.width * (this->d.depth / 8)
+		     lpdsf->s.surface_desc.dwWidth * (this->d.depth / 8)
 		     );
     
 #ifdef HAVE_LIBXXSHM
   }
 #endif
-  lpdsf->s.lpitch = img->bytes_per_line;
+  lpdsf->s.surface_desc.lPitch = img->bytes_per_line;
   
   return img;
 }
@@ -1684,39 +1779,37 @@
 	(*lpdsf)->s.ddraw             = this;
 	(*lpdsf)->ref                 = 1;
 	(*lpdsf)->lpvtbl              = (LPDIRECTDRAWSURFACE_VTABLE)&xlib_dds3vt;
+	(*lpdsf)->s.palette = NULL;
+	(*lpdsf)->t.xlib.image = NULL; /* This is for off-screen buffers */
 
 		if (!(lpddsd->dwFlags & DDSD_WIDTH))
 			lpddsd->dwWidth	 = this->d.width;
 		if (!(lpddsd->dwFlags & DDSD_HEIGHT))
 			lpddsd->dwHeight = this->d.height;
 
-	(*lpdsf)->s.width	= lpddsd->dwWidth;
-	(*lpdsf)->s.height	= lpddsd->dwHeight;
-
+	/* Check if this a 'primary surface' or not */
   if ((lpddsd->dwFlags & DDSD_CAPS) && 
-      (lpddsd->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)) {
-
-    /* Allocate surface memory */
-    (*lpdsf)->s.surface = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpddsd->dwWidth*lpddsd->dwHeight*this->d.depth/8);
-    
-    /* No XImage for a offscreen buffer */
-    (*lpdsf)->t.xlib.image = NULL;
-    (*lpdsf)->t.xlib.on_screen = FALSE;
-    (*lpdsf)->s.lpitch = lpddsd->dwWidth * (this->d.depth / 8);
-    
-    TRACE(ddraw,"using system memory for a primary surface (%p)\n", *lpdsf);
-  } else {
+	    (lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {
     XImage *img;
       
     TRACE(ddraw,"using standard XImage for a primary surface (%p)\n", *lpdsf);
 
+	  /* First, store the surface description */
+	  (*lpdsf)->s.surface_desc = *lpddsd;
+	  
     /* Create the XImage */
     img = create_ximage(this, (LPDIRECTDRAWSURFACE3) *lpdsf);
     if (img == NULL)
       return DDERR_OUTOFMEMORY;
-    
     (*lpdsf)->t.xlib.image = img;
-    (*lpdsf)->t.xlib.on_screen = TRUE;
+
+	  /* Add flags if there were not present */
+	  (*lpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE;
+	  (*lpdsf)->s.surface_desc.dwWidth = this->d.width;
+	  (*lpdsf)->s.surface_desc.dwHeight = this->d.height;
+	  (*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
+	  _getpixelformat(this,&((*lpdsf)->s.surface_desc.ddpfPixelFormat));
+	  (*lpdsf)->s.backbuffer = NULL;
     
     /* Check for backbuffers */
 	if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
@@ -1736,9 +1829,8 @@
 
 		back->ref = 1;
 		back->lpvtbl = (LPDIRECTDRAWSURFACE3_VTABLE)&xlib_dds3vt;
-
-      back->s.width = lpddsd->dwWidth;
-      back->s.height = lpddsd->dwHeight;
+	    /* Copy the surface description from the front buffer */
+	    back->s.surface_desc = (*lpdsf)->s.surface_desc;
 
       /* Create the XImage */
       img = create_ximage(this, back);
@@ -1746,10 +1838,19 @@
 	return DDERR_OUTOFMEMORY;
       back->t.xlib.image = img;
       
-      back->t.xlib.on_screen = FALSE;
 		back->s.backbuffer = NULL; /* does not have a backbuffer, it is
 					    * one! */
+
+	    /* Add relevant info to front and back buffers */
+	    (*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
+	    back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
+	    back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
+	    back->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
 	}
+	} else {
+	  /* There is no Xlib-specific code here...
+	     Go to the common surface creation function */
+	  return common_off_screen_CreateSurface(this, lpddsd, *lpdsf);
   }
   
 	return 0;
@@ -2557,7 +2658,9 @@
         ret = DefWindowProc32A(hwnd, msg, wParam, lParam );
       } 
 
-    } else {
+    }
+    else
+    {
 	ret = DefWindowProc32A(hwnd,msg,wParam,lParam);
     }
 
diff --git a/include/ddraw.h b/include/ddraw.h
index 8deb38a..1e03f8b 100644
--- a/include/ddraw.h
+++ b/include/ddraw.h
@@ -985,8 +985,8 @@
     LPDIRECTDRAWPALETTE		palette;
     LPDIRECTDRAW2		ddraw;
     LPDIRECTDRAWSURFACE3	backbuffer;
-    LPVOID			surface;
-    DWORD			lpitch,width,height;
+
+    DDSURFACEDESC               surface_desc;
 };
 
 struct _dga_directdrawsurface {
@@ -995,7 +995,6 @@
 
 struct _xlib_directdrawsurface {
     XImage		*image;
-    int                 on_screen;
 #ifdef HAVE_LIBXXSHM
     XShmSegmentInfo	shminfo;
 #endif
@@ -1013,7 +1012,8 @@
     STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE;
     STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE, LPRECT32,DWORD) PURE;
     STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE) PURE;
-    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
+    STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE;
     STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE, DWORD) PURE;
     STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE FAR *) PURE;
     STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE;
@@ -1196,5 +1196,6 @@
 HRESULT WINAPI DirectDrawCreate(LPGUID,LPDIRECTDRAW*,LPUNKNOWN);
 HRESULT WINAPI DirectDrawEnumerate32A(LPDDENUMCALLBACK32A,LPVOID);
 HRESULT WINAPI DirectDrawEnumerate32W(LPDDENUMCALLBACK32W,LPVOID);
+HRESULT WINAPI DirectDrawCreateClipper(DWORD,LPDIRECTDRAWCLIPPER*,LPUNKNOWN);
 #define DirectDrawEnumerate WINELIB_NAME_AW(DirectDrawEnumerate)
 #endif
diff --git a/relay32/ddraw.spec b/relay32/ddraw.spec
index 151a1c3..46d88b4 100644
--- a/relay32/ddraw.spec
+++ b/relay32/ddraw.spec
@@ -7,7 +7,7 @@
    4  stub DDInternalUnlock
    5  stdcall DSoundHelp(long long long) DSoundHelp
    6  stdcall DirectDrawCreate(ptr ptr ptr) DirectDrawCreate
-   7  stub DirectDrawCreateClipper
+   7  stdcall DirectDrawCreateClipper(long ptr ptr) DirectDrawCreateClipper
    8  stdcall DirectDrawEnumerateA(ptr ptr) DirectDrawEnumerate32A
    9  stub DirectDrawEnumerateW
   10  stub DllCanUnloadNow