WineX patches

Jarmo <[email protected]>
Newsgroups gmane.comp.emulators.winex.devel
Message-ID <[email protected]>
Hi,

Here is some patches.

dclipper.diff and dclipper2.diff 
patches should made DirectDrawClipper interface fully implemented. 
Unfortunately I haven't been able to test most parts of the code. 

colorkey.diff
will remove one FIXME from SetColorKey function

blitter.diff
will add new Blt function supporting DDClipper and clipping when scaling 
surfaces. Due DDClipper it should be able to blit circular areas, multible 
rectangles and so on.

this will also add important fix in BltFast function. BltFast will clip right 
and bottom borders when blitting outside destination surface. But there is no 
protection on top and left borders. This may have causen crashes in many 
games.


Due the copyprotection issues I haven't been able to test most of the games. 
Older games are usual not using DirectDraw. Copy protection binaries would 
help much. 

Regards,
Jarmo
blitter.diff (text/x-diff, 24.6 KB)
--- dsurface/dib.c	2003-06-17 12:55:56.000000000 +0000
+++ /root/wine_patch/dlls/ddraw/dsurface/dib.c	2003-07-02 21:40:09.000000000 +0000
@@ -345,29 +345,134 @@
     return DD_OK;
 }
 
+
+
+/*
+ * These functions and macros are a part of DIB_DirectDrawSurface_Blt
+ */   
+
+#define COPYBOX_COLORKEY(type) { \
+  type *d = (type *)dbuf, *s = (type *)sbuf, tmp; \
+  for (y = 0; y < h; y++) { \
+    for (x = 0; x < w; x++) { \
+      tmp = s[x]; \
+      if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
+    } \
+    (LPBYTE)s += spitch; \
+    (LPBYTE)d += dpitch; \
+  } \
+}
+
+#define STRETCH_ROW(type) { \
+		    type *s = (type *) sbuf, *d = (type *) dbuf; \
+		    for (x = sx = 0; x < w; x++, sx += xinc) \
+		    d[x] = s[sx >> 16]; \
+}
+
+#define STRETCH_ROW_24 { \
+        LPBYTE s, d = dbuf; \
+        for (x = sx = 0; x < w; x++, sx+= xinc) { \
+          DWORD pixel;\
+          s = sbuf+3*(sx>>16); \
+          pixel = (s[0]<<16)|(s[1]<<8)|s[2]; \
+          d[0] = (pixel>>16)&0xff; \
+          d[1] = (pixel>> 8)&0xff; \
+          d[2] = (pixel    )&0xff; \
+          d+=3; \
+        } \
+}
+
+
+#define COPYROW_COLORKEY(type) { \
+		type *s = (type *) sbuf, *d = (type *) dbuf, tmp; \
+		for (x = sx = 0; x < w; x++, sx += xinc) { \
+        tmp=s[sx >> 16]; \
+		    if (tmp < keylow || tmp > keyhigh ) d[x] = tmp; \
+		} \
+}
+
+BOOL __is_invalid(RECT *r)
+{
+  if (r->top>=r->bottom) return TRUE;
+  if (r->left>=r->right) return TRUE;
+  return FALSE;
+}
+
+RECT __union(RECT *a, RECT *b)
+{
+  RECT r;
+  r.top    = max(a->top, b->top);
+  r.left   = max(a->left, b->left);
+  r.right  = min(a->right, b->right);
+  r.bottom = min(a->bottom, b->bottom);
+  return r;
+}
+
+void __scale_rect(RECT *a,DWORD xm,DWORD xd,DWORD ym,DWORD yd)
+{
+  int w=(a->right-a->left)*xm/xd;
+  int h=(a->bottom-a->top)*ym/yd;
+  a->right=a->left+w;
+  a->bottom=a->top+h;
+}
+
 HRESULT WINAPI
 DIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst,
 			  LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
 			  DWORD dwFlags, LPDDBLTFX lpbltfx)
 {
-    ICOM_THIS(IDirectDrawSurfaceImpl,iface);
-    RECT		xdst,xsrc;
-    DDSURFACEDESC2	ddesc,sdesc;
+
+ ICOM_THIS(IDirectDrawSurfaceImpl,iface);
+    DDSURFACEDESC2	ddesc,sdesc;   
     HRESULT		ret = DD_OK;
-    int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
+    int bpp, srcheight, srcwidth, dstheight, dstwidth;
     int x, y;
     LPBYTE dbuf, sbuf;
+    DWORD keylow=0, keyhigh=0, xinc=0, yinc=0, fillcolor=0;
+    
+    /* Clipper Data */
+    LPDIRECTDRAWCLIPPER dClipper;
+    LPRGNDATA lpDstClipList=NULL;
+    LPRECT    lpDstRects=NULL;
+    DWORD     drcount=0;
+    DWORD     dwSize=0;  
+    RECT      DefaultDstClipRect;
+    RECT      DefaultSrcClipRect;
+    RECT      srect, drect;
 
     TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
 
     DD_STRUCT_INIT(&ddesc);
     DD_STRUCT_INIT(&sdesc);
-
+  
+     /* Make Some Checks */
+    if (dwFlags & (DDBLT_WAIT|DDBLT_ASYNC)){  
+      static BOOL displayed = FALSE;
+      if (!displayed) {
+        FIXME("dwFlags DDBLT_WAIT and/or DDBLT_ASYNC: can't handle right now.\n");
+        displayed = TRUE;
+      }
+      dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);
+    }
+    
     sdesc.dwSize = sizeof(sdesc);
     if (src) IDirectDrawSurface7_Lock(src, NULL, &sdesc, DDLOCK_READONLY, 0);
     ddesc.dwSize = sizeof(ddesc);
     IDirectDrawSurface7_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
 
+    /* Default Clipping Rectangles */
+    DefaultDstClipRect.top=DefaultDstClipRect.left=0;
+    DefaultDstClipRect.right=ddesc.dwWidth;
+    DefaultDstClipRect.bottom=ddesc.dwHeight;
+    
+    if (src) {
+    DefaultSrcClipRect.right=sdesc.dwWidth;
+    DefaultSrcClipRect.bottom=sdesc.dwHeight;
+    }
+    else DefaultSrcClipRect.right=DefaultSrcClipRect.bottom=0;
+    DefaultSrcClipRect.top=DefaultSrcClipRect.left=0;
+
+    /* Process Compressed Formats, Does not support clipping */
     if (sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
     {
        if (ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
@@ -388,285 +493,315 @@
        goto release;
     }
 
-    if (TRACE_ON(ddraw)) {
-	if (rdst) TRACE("\tdestrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
-	if (rsrc) TRACE("\tsrcrect  :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
-	TRACE("\tflags: ");
-	DDRAW_dump_DDBLT(dwFlags);
-	if (dwFlags & DDBLT_DDFX) {
-	    TRACE("\tblitfx: ");
-	    DDRAW_dump_DDBLTFX(lpbltfx->dwDDFX);
-	}
+    /* Reset mode flags */
+    BYTE has_dclipper=0;
+    BYTE has_scaling=0;
+    BYTE has_scolorkey=0;
+    BYTE has_dcolorkey=0;
+    
+    /* Access Clippers and find clipping rectangles */
+    if (IDirectDrawSurface7_GetClipper(iface, &dClipper)==DD_OK) { /* Clipper Found */            
+      if (IDirectDrawClipper_GetClipList(dClipper, rdst, NULL, &dwSize)==DD_OK) {
+        /* Allocate space for ClipList */     
+        lpDstClipList = (LPRGNDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);     
+        if (lpDstClipList && IDirectDrawClipper_GetClipList(dClipper, rdst, lpDstClipList, &dwSize)==DD_OK) {
+          has_dclipper = 1;
+          lpDstRects   = (LPRECT)lpDstClipList->Buffer;
+          drcount      = lpDstClipList->rdh.nCount;
+          TRACE("Has ClipList %lu entries\n",drcount); /* Not an error */       
+        }
+      }        
+    }
+       
+    /* Set Default Clipper for destination if no cliplist defined */
+    if (!has_dclipper) {
+      drcount=1;
+      lpDstRects=&DefaultDstClipRect;
     }
-
+    
+    /* Check that input rectangles are valid, Use defaults if NULL */  
     if (rdst) {
-	if ((rdst->top < 0) ||
-	    (rdst->left < 0) ||
-	    (rdst->bottom < 0) ||
-	    (rdst->right < 0)) {
-	  ERR(" Negative values in LPRECT !!!\n");
-	  goto release;
-	}
-	memcpy(&xdst,rdst,sizeof(xdst));
-    } else {
-	xdst.top	= 0;
-	xdst.bottom	= ddesc.dwHeight;
-	xdst.left	= 0;
-	xdst.right	= ddesc.dwWidth;
+      if (__is_invalid(rdst)) { ret=DDERR_INVALIDRECT; goto error; }
     }
+    else rdst=&DefaultDstClipRect;
 
     if (rsrc) {
-	if ((rsrc->top < 0) ||
-	    (rsrc->left < 0) ||
-	    (rsrc->bottom < 0) ||
-	    (rsrc->right < 0)) {
-	  ERR(" Negative values in LPRECT !!!\n");
-	  goto release;
-	}
-	memcpy(&xsrc,rsrc,sizeof(xsrc));
-    } else {
-	if (src) {
-	    xsrc.top	= 0;
-	    xsrc.bottom	= sdesc.dwHeight;
-	    xsrc.left	= 0;
-	    xsrc.right	= sdesc.dwWidth;
-	} else {
-	    memset(&xsrc,0,sizeof(xsrc));
-	}
-    }
-    /* broken program?? */
-    if ((src && xsrc.bottom > sdesc.dwHeight) ||
-		    (xdst.bottom > ddesc.dwHeight))
-    {
-	    ret = DDERR_INVALIDRECT;
-	    goto release;
-    }
-
-   /* This is wrong - we need to do proper clipping when stretching.  But
-      a quick hack will suffice to prevent crashes */
-    if (xdst.bottom > ddesc.dwHeight)
-    {
-        xdst.bottom = ddesc.dwHeight;
-        FIXME("Trying to stretch beyond source height bounds.  Stretching to source bounds instead of clipping\n");
-    }
-    if (xdst.right > ddesc.dwWidth)
-    {
-        xdst.right = ddesc.dwWidth;
-        FIXME("Trying to stretch beyond source width bounds.  Stretching to source bounds instead of clipping\n");
+      if (__is_invalid(rsrc)) { ret=DDERR_INVALIDRECT; goto error; }
     }
+    else rsrc=&DefaultSrcClipRect;
 
+    /* Width & Height values for original src,dst-rectangles */   
     bpp = GET_BPP(ddesc);
-    srcheight = xsrc.bottom - xsrc.top;
-    srcwidth = xsrc.right - xsrc.left;
-    dstheight = xdst.bottom - xdst.top;
-    dstwidth = xdst.right - xdst.left;
-    width = (xdst.right - xdst.left) * bpp;
-
-    assert(width <= ddesc.u1.lPitch);
-
-    dbuf = (BYTE*)ddesc.lpSurface+(xdst.top*ddesc.u1.lPitch)+(xdst.left*bpp);
-
-    if (dwFlags & (DDBLT_WAIT|DDBLT_ASYNC))
-    {
-	static BOOL displayed = FALSE;
-	if (!displayed)
-	{
-	    FIXME("dwFlags DDBLT_WAIT and/or DDBLT_ASYNC: can't handle right now.\n");
-	    displayed = TRUE;
-	}
-        dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);
+    srcheight = rsrc->bottom - rsrc->top;
+    srcwidth = rsrc->right - rsrc->left;
+    dstheight = rdst->bottom - rdst->top;
+    dstwidth = rdst->right - rdst->left;
+
+    /* Scaling configuration */   
+    if (src && (srcwidth!=dstwidth || srcheight!=dstheight)) {
+       if (iface==src && (srcwidth>dstwidth || srcheight>dstheight)) {       
+          FIXME("Can not selfcopy while enlarging.\n");
+          ret=DDERR_UNSUPPORTED; goto error;
+       }
+       if (iface==src && (rdst->left > 0 || rdst->top > 0)) {
+          FIXME("Can not perform this operation.\n");
+          ret=DDERR_UNSUPPORTED; goto error;
+       }
+       xinc = (srcwidth << 16) / dstwidth;
+       yinc = (srcheight << 16) / dstheight;
+       has_scaling=1;           
+    }
+
+    /* Configure Special Operations */
+    if (dwFlags & DDBLT_ZBUFFER) { FIXME("Z-Buffer not supported\n"); ret=DDERR_UNSUPPORTED; goto error; } 
+    if (dwFlags & DDBLT_COLORFILL) fillcolor=lpbltfx->u5.dwFillColor;
+    if (dwFlags & DDBLT_ROP) { /* Blt Raster Ops */
+      switch(lpbltfx->dwROP) {
+        case BLACKNESS: fillcolor=0;  dwFlags|=DDBLT_COLORFILL; break;
+        case WHITENESS: fillcolor=~0; dwFlags|=DDBLT_COLORFILL; break;
+        case SRCCOPY:   break;
+        case 0xAA0029: /* No-op */ break;
+        default:
+          FIXME("Unsupported raster op: %08lx  Pattern: %p\n", lpbltfx->dwROP, lpbltfx->u5.lpDDSPattern);
+          goto error;                   
+      }
+      dwFlags &= ~DDBLT_ROP;
+    }
+    if (dwFlags & DDBLT_DDFX) {  /* Blt FX */
+       ret=DDERR_UNSUPPORTED;    
+       DDRAW_dump_DDBLTFX(lpbltfx->dwDDFX);    
+       dwFlags &= ~DDBLT_DDFX;
+       goto error;
+    }
+
+    /* ColorKey Configuration */
+    if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE | DDBLT_KEYDESTOVERRIDE | DDBLT_KEYDEST)) {                                                 
+      if (dwFlags & DDBLT_KEYSRCOVERRIDE) {
+        keylow  = lpbltfx->ddckSrcColorkey.dwColorSpaceLowValue;
+        keyhigh = lpbltfx->ddckSrcColorkey.dwColorSpaceHighValue;
+        dwFlags &= ~DDBLT_KEYSRCOVERRIDE;
+        has_scolorkey=1;
+      }
+      else if (dwFlags & DDBLT_KEYDESTOVERRIDE) {
+        keylow  = lpbltfx->ddckDestColorkey.dwColorSpaceLowValue;
+        keyhigh = lpbltfx->ddckDestColorkey.dwColorSpaceHighValue;
+        dwFlags &= ~DDBLT_KEYDESTOVERRIDE;
+        has_dcolorkey=1;
+      }
+      else if ((dwFlags&DDBLT_KEYSRC) && (sdesc.dwFlags&DDSD_CKSRCBLT)) {
+        keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
+        keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
+        dwFlags &= ~DDBLT_KEYSRC;
+        has_scolorkey=1;
+      }
+      else if ((dwFlags&DDBLT_KEYDEST) && (ddesc.dwFlags&DDSD_CKDESTBLT)) {      
+        keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
+        keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
+        dwFlags &= ~DDBLT_KEYDEST;
+        has_dcolorkey=1;
+      }    
+    }
+
+    if (has_dcolorkey) {
+      FIXME("Destination colorkeying not implemented... disabled\n");
+      has_dcolorkey = has_scolorkey = 0;
+    }   
+
+  /* Primary loop for clipping operations */
+  /* Rectangles in clip list shouldn't overlap */
+
+  TRACE("Blitting %ld rectangles\n",drcount);
+  
+begin:
+    
+  while (drcount) {
+    drcount--;
+    
+    RECT rect=lpDstRects[drcount];
+
+    if (__is_invalid(&rect)) goto begin;
+
+    /* Compute operative rectangles srect and drect */
+    if (!src) drect=__union(&rect, rdst); /* Sourceless Blits */
+    else {       
+      srect=__union(&DefaultSrcClipRect, rsrc); /* Source clipping */
+      drect=__union(&rect, rdst);               /* Destination clipping */
+      int disx = rsrc->left - rdst->left;
+      int disy = rsrc->top - rdst->top;
+      OffsetRect(&drect, disx, disy);  /* Overlap and unscale for final combination */
+      if (has_scaling) __scale_rect(&drect, srcwidth, dstwidth, srcheight, dstheight);
+      drect=srect=__union(&srect, &drect); /* Combine source and distination */
+      if (has_scaling) __scale_rect(&drect, dstwidth, srcwidth, dstheight, srcheight); /* UnScale */
+      OffsetRect(&drect, -disx, -disy); /* UnTranslate */
+      if (__is_invalid(&srect)) goto begin;
+    }
+
+    int h = drect.bottom - drect.top;
+    int w = drect.right - drect.left;
+    if (w<=0 || h<=0) goto begin;
+    DWORD width=w*bpp;
+
+    if (!src) { /* Sourceless operations */
+     
+      dbuf = (BYTE*)ddesc.lpSurface+(drect.top*ddesc.u1.lPitch)+(drect.left*bpp);
+       
+      if (dwFlags & DDBLT_COLORFILL) {
+        ret = _Blt_ColorFill(dbuf, w, h, bpp, ddesc.u1.lPitch, fillcolor);
+        dwFlags &= ~DDBLT_COLORFILL;
+        if (ret!=DD_OK) goto begin;
+        goto error;
+      }
+      /* This relies on the underlying hal driver to copy the z dib bits into the GL z-buffer */
+      if (dwFlags & DDBLT_DEPTHFILL) {
+        ret = _Blt_ColorFill(dbuf, w, h, bpp, ddesc.u1.lPitch, lpbltfx->u5.dwFillDepth);
+        dwFlags &= ~DDBLT_DEPTHFILL;
+        if (ret!=DD_OK) goto begin;
+        goto error;
+      }
+      if (dwFlags & DDBLT_DDROPS) {
+        FIXME("\tDdraw Raster Ops: %08lx  Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->u5.lpDDSPattern);
+        ret=DDERR_UNSUPPORTED;
+        dwFlags &= ~DDBLT_DDROPS;
+        goto error;
+      }    
     }
 
-    /* First, all the 'source-less' blits */
-    if (dwFlags & DDBLT_COLORFILL) {
-	ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
-			     ddesc.u1.lPitch, lpbltfx->u5.dwFillColor);
-	dwFlags &= ~DDBLT_COLORFILL;
-    }
-
-    if (dwFlags & DDBLT_DEPTHFILL) {
-        /* This relies on the underlying hal driver to copy the z dib bits
-           into the GL z-buffer */
-	ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
-			     ddesc.u1.lPitch, lpbltfx->u5.dwFillDepth);
-	dwFlags &= ~DDBLT_DEPTHFILL;
-    }
-
-    if (dwFlags & DDBLT_ROP) {
-	/* Catch some degenerate cases here */
-	switch(lpbltfx->dwROP) {
-	case BLACKNESS:
-	    ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.u1.lPitch,0);
-	    break;
-	case 0xAA0029: /* No-op */
-	    break;
-	case WHITENESS:
-	    ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.u1.lPitch,~0);
-	    break;
-	case SRCCOPY: /* well, we do that below ? */
-	    break;
-	default:
-	    FIXME("Unsupported raster op: %08lx  Pattern: %p\n", lpbltfx->dwROP, lpbltfx->u5.lpDDSPattern);
-	    goto error;
-	}
-	dwFlags &= ~DDBLT_ROP;
-    }
-    if (dwFlags & DDBLT_DDROPS) {
-	FIXME("\tDdraw Raster Ops: %08lx  Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->u5.lpDDSPattern);
-    }
-    /* Now the 'with source' blits */
-    if (src) {
-	LPBYTE sbase;
-	int sx, xinc, sy, yinc;
 
-	if (!dstwidth || !dstheight) /* hmm... stupid program ? */
-	    goto release;
-	sbase = (BYTE*)sdesc.lpSurface+(xsrc.top*sdesc.u1.lPitch)+xsrc.left*bpp;
-	xinc = (srcwidth << 16) / dstwidth;
-	yinc = (srcheight << 16) / dstheight;
-
-	if (!dwFlags) {
-	    /* No effects, we can cheat here */
-	    if (dstwidth == srcwidth) {
-		if (dstheight == srcheight) {
-		    /* No stretching in either direction. This needs to be as
-		     * fast as possible */
-		    LONG spitch = sdesc.u1.lPitch;
-		    LONG dpitch = ddesc.u1.lPitch;
-
-		    sbuf = sbase;
-
-		    /* Detect self-copies and ensure that we copy rows in the
-		     * right order to avoid overwriting a that is still needed.
-		     * (memmove is used to ensure that the pixels in a row are
-		     * copied in the right order.) */
-		    if (src == iface && xsrc.top < xdst.top)
-		    {
-			LPBYTE surf = (BYTE*)sdesc.lpSurface;
-			sbuf = surf + (xsrc.bottom-1)*spitch + xsrc.left*bpp;
-			dbuf = surf + (xdst.bottom-1)*dpitch + xdst.left*bpp;
-
-			spitch = -spitch;
-			dpitch = -dpitch;
-		    }
-
-		    for (y = 0; y < dstheight; y++) {
-			memmove(dbuf, sbuf, width);
-			sbuf += spitch;
-			dbuf += dpitch;
-		    }
-		} else {
-		    /* Stretching in Y direction only */
-		    for (y = sy = 0; y < dstheight; y++, sy += yinc) {
-			sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch;
-			memmove(dbuf, sbuf, width);
-			dbuf += ddesc.u1.lPitch;
-		    }
-		}
-	    } else {
-		/* Stretching in X direction */
-		int last_sy = -1;
-		for (y = sy = 0; y < dstheight; y++, sy += yinc) {
-		    sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch;
-
-		    if ((sy >> 16) == (last_sy >> 16)) {
-			/* this sourcerow is the same as last sourcerow -
-			 * copy already stretched row
-			 */
-			memmove(dbuf, dbuf - ddesc.u1.lPitch, width);
-		    } else {
-#define STRETCH_ROW(type) { \
-		    type *s = (type *) sbuf, *d = (type *) dbuf; \
-		    for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
-		    d[x] = s[sx >> 16]; \
-		    break; }
 
-		    switch(bpp) {
-		    case 1: STRETCH_ROW(BYTE)
-		    case 2: STRETCH_ROW(WORD)
-		    case 4: STRETCH_ROW(DWORD)
-		    case 3: {
-			LPBYTE s,d = dbuf;
-			for (x = sx = 0; x < dstwidth; x++, sx+= xinc) {
-			    DWORD pixel;
-
-			    s = sbuf+3*(sx>>16);
-			    pixel = (s[0]<<16)|(s[1]<<8)|s[2];
-			    d[0] = (pixel>>16)&0xff;
-			    d[1] = (pixel>> 8)&0xff;
-			    d[2] = (pixel    )&0xff;
-			    d+=3;
-			}
-			break;
-		    }
-		    default:
-			FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
-			ret = DDERR_UNSUPPORTED;
-			goto error;
-		    }
-#undef STRETCH_ROW
-		    }
-		    dbuf += ddesc.u1.lPitch;
-		    last_sy = sy;
-		}
-	    }
-	} else if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE | DDBLT_KEYDEST)) {
-	    DWORD keylow, keyhigh;
-
-	    if (dwFlags & DDBLT_KEYSRCOVERRIDE) {
-		keylow  = lpbltfx->ddckSrcColorkey.dwColorSpaceLowValue;
-		keyhigh = lpbltfx->ddckSrcColorkey.dwColorSpaceHighValue;
-	    } else if (dwFlags & DDBLT_KEYSRC) {
-		keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
-		keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
-	    } else {
-		/* I'm not sure if this is correct */
-		FIXME("DDBLT_KEYDEST not fully supported yet.\n");
-		keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
-		keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
-	    }
 
+    
+    /* Operations With Source */
+    
+    if (src) {
 
-	    for (y = sy = 0; y < dstheight; y++, sy += yinc) {
-		sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch;
-
-#define COPYROW_COLORKEY(type) { \
-		type *s = (type *) sbuf, *d = (type *) dbuf, tmp; \
-		for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
-		    tmp = s[sx >> 16]; \
-		    if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
-		} \
-		break; }
-
-		switch (bpp) {
-		case 1: COPYROW_COLORKEY(BYTE)
-		case 2: COPYROW_COLORKEY(WORD)
-		case 4: COPYROW_COLORKEY(DWORD)
-		default:
-		    FIXME("%s color-keyed blit not implemented for bpp %d!\n",
-		    (dwFlags & DDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
-		    ret = DDERR_UNSUPPORTED;
-		    goto error;
-		}
-		dbuf += ddesc.u1.lPitch;
-	    }
-#undef COPYROW_COLORKEY
-	    dwFlags &= ~(DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE | DDBLT_KEYDEST);
-	}
-    }
+      LONG spitch = sdesc.u1.lPitch;
+      LONG dpitch = ddesc.u1.lPitch;
+      dbuf = (BYTE*)ddesc.lpSurface+(drect.top*ddesc.u1.lPitch)+(drect.left*bpp);
+      sbuf = (BYTE*)sdesc.lpSurface+(srect.top*sdesc.u1.lPitch)+(srect.left*bpp);
+          
+      /* Copy Source to Destination */
+      if (!has_scaling) {
+
+        if (!(has_scolorkey || has_dcolorkey)) { /* Copy without colorkey */
+
+         /* Detect self-copies and ensure that we copy rows in the
+  	      * right order to avoid overwriting a that is still needed.
+  	      * (memmove is used to ensure that the pixels in a row are
+  	      * copied in the right order.) */
+          if (src == iface && srect.top < drect.top) {
+      	    LPBYTE surf = (BYTE*)sdesc.lpSurface;
+      	    sbuf = surf + (srect.bottom-1)*spitch + srect.left*bpp;
+      	    dbuf = surf + (drect.top+h-1)*dpitch + drect.left*bpp;
+      	    spitch = -sdesc.u1.lPitch;
+      	    dpitch = -ddesc.u1.lPitch;
+          }               
+          for (y = 0; y < h; y++) {
+  	        memmove(dbuf, sbuf, width);
+  	        sbuf += spitch;
+  	        dbuf += dpitch;
+  	      }
+          goto begin;
+        }
+        else {  /* Copy with colorkey */
+          switch (bpp) {
+          case 1: COPYBOX_COLORKEY(BYTE)  break;
+          case 2: COPYBOX_COLORKEY(WORD)  break;
+          case 4: COPYBOX_COLORKEY(DWORD) break;
+          default:
+            FIXME("Color key blitting not supported for bpp %d\n",bpp*8);
+            ret = DDERR_UNSUPPORTED; goto error;
+          }
+          goto begin;
+        }
+      } /* !has_scaling */
+
+      /* Copy with scaling */
+      if (has_scaling) {
+        LPBYTE sbase;
+        int sx, sy;
+        sbase = (BYTE*)sdesc.lpSurface+(srect.top*sdesc.u1.lPitch)+srect.left*bpp;
+  
+        if (!has_scolorkey) {
+          if (dstwidth == srcwidth) { /* Stretching in Y direction only */        
+            for (y = sy = 0; y < h; y++, sy += yinc) {
+                sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch;
+                memmove(dbuf, sbuf, width);
+                dbuf += ddesc.u1.lPitch;
+            }
+            goto begin;
+          }
+
+          /* Stretch all directions */
+          int last_sy = -1;             
+          for (y = sy = 0; y < h; y++, sy += yinc) {
+            sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch;
+            if ((sy >> 16) == (last_sy >> 16)) {
+              /* this sourcerow is the same as last sourcerow copy already stretched row */
+              memmove(dbuf, dbuf - ddesc.u1.lPitch, width);
+            }
+            else {
+              switch(bpp) {
+              case 1: STRETCH_ROW(BYTE) break;
+              case 2: STRETCH_ROW(WORD) break;
+              case 4: STRETCH_ROW(DWORD) break;
+              case 3: STRETCH_ROW_24 break;            
+              default:
+                FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
+                ret = DDERR_UNSUPPORTED; goto error;
+              }
+            } 
+            dbuf += ddesc.u1.lPitch;
+            last_sy = sy;
+          }
+          goto begin;         
+        } /* !has_colorkey */ 
+
+        if (has_scolorkey) {
+          for (y = sy = 0; y < h; y++, sy += yinc) {
+            sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch;
+
+            switch (bpp) {
+              case 1: COPYROW_COLORKEY(BYTE) break;
+              case 2: COPYROW_COLORKEY(WORD) break;
+              case 4: COPYROW_COLORKEY(DWORD) break;
+              default:
+                FIXME("Color-keyed blit not implemented for bpp %d!\n",bpp*8);
+                ret = DDERR_UNSUPPORTED;
+                goto error;
+            }
+            dbuf += ddesc.u1.lPitch;
+          }
+          goto begin;
+                  
+        } /* has_scolorkey */
+            
+      } /* has_scaling */
+         
+    } /* has_srccopy */
+  } /* main loop ends */          
 
 error:
+release:
+
     if (dwFlags && FIXME_ON(ddraw)) {
-	FIXME("\tUnsupported flags: ");
-	DDRAW_dump_DDBLT(dwFlags);
+      FIXME("\tUnsupported flags: ");
+      DDRAW_dump_DDBLT(dwFlags);
     }
 
-release:
+    if (lpDstClipList) HeapFree(GetProcessHeap(), 0, lpDstClipList);
+    
     IDirectDrawSurface7_Unlock(iface,NULL);
     if (src) IDirectDrawSurface7_Unlock(src,NULL);
     return ret;
 }
 
+#undef COPYBOX_COLORKEY
+#undef STRETCH_ROW
+#undef COPYROW_COLORKEY
+#undef STRETCH_ROW_24
+   
+
+
 /* BltBatch: generic, unimplemented */
 
 HRESULT WINAPI
@@ -721,29 +856,36 @@
        }
        goto release;
     }
-
+  
    if (!rsrc) {
-	   WARN("rsrc is NULL!\n");
 	   rsrc = &rsrc2;
 	   rsrc->left = rsrc->top = 0;
 	   rsrc->right = sdesc.dwWidth;
 	   rsrc->bottom = sdesc.dwHeight;
    }
+   
+   h=rsrc->bottom-rsrc->top;
+   w=rsrc->right-rsrc->left;
+
+   /* Check that rect is valid */
+   if (h<0 || w<0) {  ret=DDERR_INVALIDRECT; goto error; }
+
+   /* This will prevent blitting over left and top borders */      
+   if (dstx>ddesc.dwWidth || dsty>ddesc.dwHeight || rsrc->left<0 || rsrc->top<0) {
+     ret=DDERR_INVALIDPARAMS; goto error;
+   } 
 
     bpp = GET_BPP(This->surface_desc);
     sbuf = (BYTE *)sdesc.lpSurface+(rsrc->top*sdesc.u1.lPitch)+rsrc->left*bpp;
     dbuf = (BYTE *)ddesc.lpSurface+(dsty*ddesc.u1.lPitch)+dstx* bpp;
 
 
-    h=rsrc->bottom-rsrc->top;
     if (h>ddesc.dwHeight-dsty) h=ddesc.dwHeight-dsty;
     if (h>sdesc.dwHeight-rsrc->top) h=sdesc.dwHeight-rsrc->top;
-    if (h<0) h=0;
-
-    w=rsrc->right-rsrc->left;
+      
     if (w>ddesc.dwWidth-dstx) w=ddesc.dwWidth-dstx;
     if (w>sdesc.dwWidth-rsrc->left) w=sdesc.dwWidth-rsrc->left;
-    if (w<0) w=0;
+    if (w<=0 || h<=0) goto release;
 
     if (trans & (DDBLTFAST_SRCCOLORKEY | DDBLTFAST_DESTCOLORKEY)) {
 	DWORD keylow, keyhigh;
@@ -757,6 +899,8 @@
 	    keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
 	}
 
+/* I think that key values should be compared differently for every R,G,B-component */
+/* This may not work unless low and high keys are the same (in most cases thay are) */
 #define COPYBOX_COLORKEY(type) { \
     type *d = (type *)dbuf, *s = (type *)sbuf, tmp; \
     s = (type *) ((BYTE *) sdesc.lpSurface + (rsrc->top * sdesc.u1.lPitch) + rsrc->left * bpp); \
colorkey.diff (text/x-diff, 1.6 KB)
--- dsurface/main.c	2003-07-02 22:02:02.000000000 +0000
+++ /root/wine_patch/dlls/ddraw/dsurface/main.c	2003-07-02 22:03:18.000000000 +0000
@@ -1168,6 +1168,7 @@
     return DD_OK;
 }
 
+
 HRESULT WINAPI
 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
 				   DWORD dwFlags, LPDDCOLORKEY pCKey)
@@ -1177,27 +1178,38 @@
     TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
     if (pCKey == NULL)
     {
-	FIXME("supposedly removing color key %lu\n",
-	      dwFlags & ~DDCKEY_COLORSPACE);
-	return DD_OK;
+      switch (dwFlags & ~DDCKEY_COLORSPACE){
+        case DDCKEY_DESTBLT: This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT; break;
+        case DDCKEY_DESTOVERLAY: This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY; break;
+        case DDCKEY_SRCOVERLAY: This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY; break;
+        case DDCKEY_SRCBLT: This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT; break;
+        default:
+          ERR("Invalid parameter\n");
+	        return DDERR_INVALIDPARAMS;
+      }
+	  return DD_OK;
     }
 
     switch (dwFlags & ~DDCKEY_COLORSPACE)
     {
     case DDCKEY_DESTBLT:
 	This->surface_desc.ddckCKDestBlt = *pCKey;
+  This->surface_desc.dwFlags|=DDSD_CKDESTBLT;
 	break;
 
     case DDCKEY_DESTOVERLAY:
 	This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
+  This->surface_desc.dwFlags|=DDSD_CKDESTOVERLAY;
 	break;
 
     case DDCKEY_SRCOVERLAY:
 	This->surface_desc.ddckCKSrcOverlay = *pCKey;
+  This->surface_desc.dwFlags|=DDSD_CKSRCOVERLAY;
 	break;
 
     case DDCKEY_SRCBLT:
 	This->surface_desc.ddckCKSrcBlt = *pCKey;
+  This->surface_desc.dwFlags|=DDSD_CKSRCBLT;
 	break;
 
     default:
dclipper2.diff (text/x-diff, 359 B)
--- ddraw_private.h	2003-05-16 13:03:09.000000000 +0000
+++ /root/wine_patch/dlls/ddraw/ddraw_private.h	2003-07-02 20:10:07.000000000 +0000
@@ -220,7 +220,8 @@
 
     /* IDirectDrawClipper fields */
     HWND hWnd;
-
+    HRGN rgncopy;
+    
     IDirectDrawImpl* ddraw_owner;
     IDirectDrawClipperImpl* prev_ddraw;
     IDirectDrawClipperImpl* next_ddraw;
dclipper.diff (text/x-diff, 4.9 KB)
Common subdirectories: dclipper/CVS and /root/wine_patch/dlls/ddraw/dclipper/CVS
diff -u dclipper/main.c /root/wine_patch/dlls/ddraw/dclipper/main.c
--- dclipper/main.c	2002-09-25 20:23:14.000000000 +0000
+++ /root/wine_patch/dlls/ddraw/dclipper/main.c	2003-07-02 21:32:50.000000000 +0000
@@ -2,6 +2,9 @@
  *
  * Copyright 2000 Marcus Meissner
  * Copyright 2000-2001 TransGaming Technologies Inc.
+ *
+ * Modifications:
+ * Copyright 2003 Jarmo Nikkanen
  */
 
 #include "config.h"
@@ -17,6 +20,9 @@
 #include "ddraw/main.h"
 
 #include "debugtools.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "win.h"
 
 DEFAULT_DEBUG_CHANNEL(ddraw);
 
@@ -42,6 +48,7 @@
     This->ref = 1;
     This->hWnd = 0;
     This->ddraw_owner = NULL;
+    This->rgncopy = 0;
 
     *lplpDDClipper = ICOM_INTERFACE(This, IDirectDrawClipper);
     return DD_OK;
@@ -76,6 +83,12 @@
 	return DDERR_INVALIDPARAMS;
     }
 
+    WND *wnd = WIN_GetPtr( hWnd );
+    if (!wnd) return DDERR_GENERIC;
+    if (!This->rgncopy) This->rgncopy=CreateRectRgn(0,0,0,0);
+    CombineRgn(This->rgncopy, wnd->hrgnWnd, 0, RGN_COPY);
+    WIN_ReleasePtr( wnd );
+
     This->hWnd = hWnd;
     return DD_OK;
 }
@@ -85,6 +98,9 @@
     if (This->ddraw_owner != NULL)
 	Main_DirectDraw_RemoveClipper(This->ddraw_owner, This);
 
+    if (This->rgncopy) DeleteObject(This->rgncopy);
+    This->rgncopy = 0;
+
     HeapFree(GetProcessHeap(), 0 ,This);
 }
 
@@ -110,18 +126,79 @@
     LPDIRECTDRAWCLIPPER iface,LPRECT prcClip,LPRGNDATA lprgn,LPDWORD pdwSize
 ) {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
-    static int warned = 0;
-    if (warned++ < 10)
-	FIXME("(%p,%p,%p,%p),stub!\n",This,prcClip,lprgn,pdwSize);
-    if (pdwSize) *pdwSize=0;
-    return DDERR_NOCLIPLIST;
+    TRACE("(%p,%p,%p,%p)\n",This,prcClip,lprgn,pdwSize);
+    int ret=DD_OK;
+    WND *wnd=NULL;
+    HRGN dst=0;
+
+    if (This->hWnd) { /* Clipper is connected to window, I hope this is correct */
+        wnd = WIN_GetPtr( This->hWnd );
+        if (!wnd) { ERR("Critical ! !\n"); return DDERR_GENERIC; }
+
+        HRGN hRgn=wnd->hrgnWnd;
+        if (!hRgn) { ret=DDERR_NOCLIPLIST; goto release; }   
+            
+        if (!prcClip) {
+           *pdwSize=GetRegionData(hRgn, *pdwSize, lprgn);     
+            if (*pdwSize==0) { ret=DDERR_NOCLIPLIST; goto release; }
+            goto release;
+        }
+        
+        if (prcClip) {
+            dst=CreateRectRgnIndirect(prcClip);         
+            int r = CombineRgn(dst, dst, hRgn, RGN_OR);
+            if (r==ERROR || r==NULLREGION) goto release;
+
+            *pdwSize=GetRegionData(dst, *pdwSize, lprgn);
+            if (*pdwSize!=1) { ret=DDERR_GENERIC; goto release; }
+            goto release;    
+        }                               
+    } /* Window association */
+
+      
+    if (This->rgncopy==0) {
+      *pdwSize=0; ret=DDERR_NOCLIPLIST;
+      goto release;
+    }
+    
+    if (prcClip==NULL) {
+      *pdwSize=GetRegionData(This->rgncopy, *pdwSize, lprgn);
+      if (*pdwSize==0) { ret=DDERR_NOCLIPLIST; goto release; }
+      goto release;
+    }
+    
+    if (prcClip!=NULL) {            
+      dst=CreateRectRgnIndirect(prcClip);
+      int r = CombineRgn(dst, dst, This->rgncopy, RGN_OR);
+      if (r==ERROR || r==NULLREGION) {
+        ret=DDERR_NOCLIPLIST;
+        goto release;
+      }
+      
+      *pdwSize=GetRegionData(dst, *pdwSize, lprgn);
+      if (*pdwSize!=1) { ret=DDERR_GENERIC; goto release; }
+      goto release;         
+    }
+          
+release:
+    if (dst) DeleteObject(dst);
+    if (wnd) WIN_ReleasePtr( wnd );
+    return ret;
 }
 
 HRESULT WINAPI Main_DirectDrawClipper_SetClipList(
     LPDIRECTDRAWCLIPPER iface,LPRGNDATA lprgn,DWORD pdwSize
 ) {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
-    FIXME("(%p,%p,%ld),stub!\n",This,lprgn,pdwSize);
+    TRACE("(%p,%p,%ld)\n",This,lprgn,pdwSize);
+
+    if (This->hWnd)  return DDERR_CLIPPERISUSINGHWND;
+    if (This->rgncopy) DeleteObject(This->rgncopy);
+    if (lprgn) {
+      This->rgncopy=ExtCreateRegion(NULL, 0, lprgn);
+      if (This->rgncopy==0) return DDERR_GENERIC;
+    } 
+    else This->rgncopy=0;
     return DD_OK;
 }
 
@@ -181,11 +258,20 @@
     LPDIRECTDRAWCLIPPER iface, BOOL* lpbChanged
 ) {
     ICOM_THIS(IDirectDrawClipperImpl,iface);
-    FIXME("(%p)->(%p),stub!\n",This,lpbChanged);
+    TRACE("(%p)->(%p)\n",This,lpbChanged);
 
-    /* XXX What is safest? */
     *lpbChanged = FALSE;
-
+    if (This->hWnd) {
+      WND *wnd = WIN_GetPtr( This->hWnd );
+      if (!wnd) return DDERR_GENERIC;
+      if (!This->rgncopy || !EqualRgn(This->rgncopy, wnd->hrgnWnd)) {   
+        *lpbChanged = TRUE;
+        if (!This->rgncopy) This->rgncopy=CreateRectRgn(0,0,0,0);
+        CombineRgn(This->rgncopy, wnd->hrgnWnd, 0, RGN_COPY);
+      }      
+      WIN_ReleasePtr( wnd );         
+    }
+    else return DDERR_INVALIDOBJECT;
     return DD_OK;
 }
 
Only in /root/wine_patch/dlls/ddraw/dclipper/: main.o
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.