Arcanum on cedega
Artur Komarov <[email protected]> Sun, 25 Sep 2005 19:07:51 +0400
| Newsgroups | gmane.comp.emulators.winex.devel |
|---|---|
| Message-ID | <[email protected]> |
--=-fjHrW5KRGmT7HO6R7HAd Content-Type: text/plain Content-Transfer-Encoding: 7bit I created patch for cvs cedega based on wine. It's fixes graphics corruption in game. (bit-blit transformation implement) next. game loading very slowly. wine do it up to 100x faster. i think it's in ntdll part. solutions expected? -- Artur Komarov <[email protected]> --=-fjHrW5KRGmT7HO6R7HAd Content-Disposition: attachment; filename=cedega-blt.patch Content-Type: text/x-patch; name=cedega-blt.patch; charset=UTF-8 Content-Transfer-Encoding: 7bit diff -rub winex-old/dlls/ddraw/dsurface/dib.c winex/dlls/ddraw/dsurface/dib.c --- winex-old/dlls/ddraw/dsurface/dib.c 2005-09-25 05:35:26.000000000 +0400 +++ winex/dlls/ddraw/dsurface/dib.c 2005-09-25 05:21:04.000000000 +0400 @@ -439,414 +439,454 @@ LPDIRECTDRAWSURFACE7 src, LPRECT rsrc, DWORD dwFlags, LPDDBLTFX lpbltfx) { - ICOM_THIS(IDirectDrawSurfaceImpl,iface); + RECT xdst,xsrc; DDSURFACEDESC2 ddesc,sdesc; HRESULT ret = DD_OK; - int bpp, srcheight, srcwidth, dstheight, dstwidth; + int bpp, srcheight, srcwidth, dstheight, dstwidth, width; 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; - - /* Reset mode flags */ - BYTE has_dclipper=0; - BYTE has_scaling=0; - BYTE has_scolorkey=0; - BYTE has_dcolorkey=0; TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx); - CHECK_LOST(This); + if (TRACE_ON(ddraw)) { + if (rdst) TRACE("\tdestrect :%ldx%ld-%ldx%ld\n",rdst->left,rdst->top,rdst->right,rdst->bottom); + if (rsrc) TRACE("\tsrcrect :%ldx%ld-%ldx%ld\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); + } + } + + /* First, check if the possible override function handles this case */ + /* if (This->aux_blt != NULL) { + if (This->aux_blt(This, rdst, src, rsrc, dwFlags, lpbltfx) == DD_OK) return DD_OK; + } */ 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; + if (rdst) { + memcpy(&xdst,rdst,sizeof(xdst)); } else { - DefaultSrcClipRect.right = DefaultSrcClipRect.bottom = 0; + xdst.top = 0; + xdst.bottom = ddesc.dwHeight; + xdst.left = 0; + xdst.right = ddesc.dwWidth; } - DefaultSrcClipRect.top = DefaultSrcClipRect.left = 0; - /* Process Compressed Formats */ - if (sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) - { - if (ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) { - if (sdesc.u4.ddpfPixelFormat.dwFourCC == ddesc.u4.ddpfPixelFormat.dwFourCC && - sdesc.u1.dwLinearSize == ddesc.u1.dwLinearSize) { - memcpy(ddesc.lpSurface, sdesc.lpSurface, ddesc.u1.dwLinearSize); + if (rsrc) { + memcpy(&xsrc,rsrc,sizeof(xsrc)); } else { - FIXME("trying to decompress %4.4s surface to %4.4s surface\n", (char*)&sdesc.u4.ddpfPixelFormat.dwFourCC, - (char*)&ddesc.u4.ddpfPixelFormat.dwFourCC); - } + if (src) { + xsrc.top = 0; + xsrc.bottom = sdesc.dwHeight; + xsrc.left = 0; + xsrc.right = sdesc.dwWidth; } else { - FIXME("software-decompression of %4.4s surface not supported\n", (char*)&sdesc.u4.ddpfPixelFormat.dwFourCC); - /* most compression algorithms are patented, which limits source distribution... - * patented software decompressors will only be available in the WineX binaries */ - /* here, we'll just clear the destination surface */ - memset(ddesc.lpSurface, 0, ddesc.u1.lPitch * ddesc.dwHeight); + memset(&xsrc,0,sizeof(xsrc)); } - goto release; } - - /* Access Clippers and find clipping rectangles */ - if (IDirectDrawSurface7_GetClipper(iface, &dClipper)==DD_OK) { /* Clipper Found */ - /* Query clipper size */ - if (IDirectDrawClipper_GetClipList(dClipper, &DefaultDstClipRect, NULL, &dwSize)==DD_OK) { - /* Allocate space for ClipList */ - lpDstClipList = (LPRGNDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); - if (lpDstClipList && IDirectDrawClipper_GetClipList(dClipper, &DefaultDstClipRect, lpDstClipList, &dwSize)==DD_OK) { - has_dclipper = 1; - lpDstRects = (LPRECT)lpDstClipList->Buffer; /* Pointer to rectangles */ - drcount = lpDstClipList->rdh.nCount; /* How many rectangles we have */ - TRACE("Has ClipList %lu entries\n",drcount); - if (TRACE_ON(ddraw)) { - DWORD i; - for (i=0; i<drcount; i++) { - TRACE("%lu: (%d, %d, %d, %d)\n",i+1,lpDstRects[i].left,lpDstRects[i].top, - lpDstRects[i].right,lpDstRects[i].bottom); + /* First check for the validity of source / destination rectangles. This was + verified using a test application + by MSDN. + */ + if ((src != NULL) && + ((xsrc.bottom > sdesc.dwHeight) || (xsrc.bottom < 0) || + (xsrc.top > sdesc.dwHeight) || (xsrc.top < 0) || + (xsrc.left > sdesc.dwWidth) || (xsrc.left < 0) || + (xsrc.right > sdesc.dwWidth) || (xsrc.right < 0) || + (xsrc.right < xsrc.left) || (xsrc.bottom < xsrc.top))) { + WARN("Application gave us bad source rectangle for Blt.\n"); + return DDERR_INVALIDRECT; + } + /* For the Destination rect, it can be out of bounds on the condition that a clipper + is set for the given surface. + */ + if ((This->clipper == NULL) && + ((xdst.bottom > ddesc.dwHeight) || (xdst.bottom < 0) || + (xdst.top > ddesc.dwHeight) || (xdst.top < 0) || + (xdst.left > ddesc.dwWidth) || (xdst.left < 0) || + (xdst.right > ddesc.dwWidth) || (xdst.right < 0) || + (xdst.right < xdst.left) || (xdst.bottom < xdst.top))) { + WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n"); + return DDERR_INVALIDRECT; + } + + /* Now handle negative values in the rectangles. Warning: only supported for now + in the 'simple' cases (ie not in any stretching / rotation cases). + + First, the case where nothing is to be done. + */ + if (((xdst.bottom <= 0) || (xdst.right <= 0) || (xdst.top >= (int) ddesc.dwHeight) || (xdst.left >= (int) ddesc.dwWidth)) || + ((src != NULL) && + ((xsrc.bottom <= 0) || (xsrc.right <= 0) || (xsrc.top >= (int) sdesc.dwHeight) || (xsrc.left >= (int) sdesc.dwWidth)))) + { + TRACE("Nothing to be done !\n"); + goto release; } + + /* The easy case : the source-less blits.... */ + if (src == NULL) { + RECT full_rect; + RECT temp_rect; /* No idea if intersect rect can be the same as one of the source rect */ + + full_rect.left = 0; + full_rect.top = 0; + full_rect.right = ddesc.dwWidth; + full_rect.bottom = ddesc.dwHeight; + IntersectRect(&temp_rect, &full_rect, &xdst); + xdst = temp_rect; + } else { + /* Only handle clipping on the destination rectangle */ + int clip_horiz = (xdst.left < 0) || (xdst.right > (int) ddesc.dwWidth ); + int clip_vert = (xdst.top < 0) || (xdst.bottom > (int) ddesc.dwHeight); + if (clip_vert || clip_horiz) { + /* Now check if this is a special case or not... */ + if ((((xdst.bottom - xdst.top ) != (xsrc.bottom - xsrc.top )) && clip_vert ) || + (((xdst.right - xdst.left) != (xsrc.right - xsrc.left)) && clip_horiz) || + (dwFlags & DDBLT_DDFX)) { + WARN("Out of screen rectangle in special case. Not handled right now.\n"); + goto release; } + if (clip_horiz) { + if (xdst.left < 0) { xsrc.left -= xdst.left; xdst.left = 0; } + if (xdst.right > ddesc.dwWidth) { xsrc.right -= (xdst.right - (int) ddesc.dwWidth); xdst.right = (int) ddesc.dwWidth; } + } + if (clip_vert) { + if (xdst.top < 0) { xsrc.top -= xdst.top; xdst.top = 0; } + if (xdst.bottom > ddesc.dwHeight) { xsrc.bottom -= (xdst.bottom - (int) ddesc.dwHeight); xdst.bottom = (int) ddesc.dwHeight; } + } + /* And check if after clipping something is still to be done... */ + if ((xdst.bottom <= 0) || (xdst.right <= 0) || (xdst.top >= (int) ddesc.dwHeight) || (xdst.left >= (int) ddesc.dwWidth) || + (xsrc.bottom <= 0) || (xsrc.right <= 0) || (xsrc.top >= (int) sdesc.dwHeight) || (xsrc.left >= (int) sdesc.dwWidth)) { + TRACE("Nothing to be done after clipping !\n"); + goto release; } } - IDirectDrawClipper_Release(dClipper); } - /* Set Default clip-rectangle for destination if no cliplist defined */ - if (!has_dclipper) { - drcount=1; - lpDstRects=&DefaultDstClipRect; - } + 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; - /* Check that input rectangles are valid, Use defaults if NULL */ - if (rdst) { - if (__is_invalid(rdst)) { ret=DDERR_INVALIDRECT; goto error; } - } else { - rdst = &DefaultDstClipRect; - } + assert(width <= ddesc.u1.lPitch); - if (rsrc) { - if (__is_invalid(rsrc)) { ret=DDERR_INVALIDRECT; goto error; } - } else { - rsrc = &DefaultSrcClipRect; - } + dbuf = (BYTE*)ddesc.lpSurface+(xdst.top*ddesc.u1.lPitch)+(xdst.left*bpp); - /* Width & Height values for original src,dst-rectangles */ - bpp = GET_BPP(ddesc); - 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; + 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; } - xinc = (srcwidth << 16) / dstwidth; - yinc = (srcheight << 16) / dstheight; - has_scaling=1; + dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC); } - /* 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 */ + /* 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) + FIXME("DDBLT_DEPTHFILL needs to be implemented!\n"); + if (dwFlags & DDBLT_ROP) { + /* Catch some degenerate cases here */ 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; + 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_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) { - if (sdesc.dwFlags&DDSD_CKSRCBLT) { - keylow = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue; - keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue; - has_scolorkey=1; - } - dwFlags &= ~DDBLT_KEYSRC; - } - else if (dwFlags&DDBLT_KEYDEST) { - if (ddesc.dwFlags&DDSD_CKDESTBLT) { - keylow = ddesc.ddckCKDestBlt.dwColorSpaceLowValue; - keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue; - has_dcolorkey=1; - } - dwFlags &= ~DDBLT_KEYDEST; - } - if (has_scolorkey==0 && has_dcolorkey==0) goto release; - } - - 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("Start blitting %ld rectangles\n",drcount); - - while (drcount) { - int w, h; - DWORD width; - - drcount--; - - if (has_dclipper) { /* We have a clipper */ - RECT rect = lpDstRects[drcount]; - if (__is_invalid(&rect)) { continue; } /*** ABORT this iteration ***/ - - /* Compute operative rectangles srect and drect */ - if (!src) { - drect = __intersect(&rect, rdst); /* Sourceless Blits */ - } else { - int disx = rsrc->left - rdst->left; - int disy = rsrc->top - rdst->top; - - drect = __intersect(&rect, rdst); /* Destination clipping */ - if (__is_invalid(&drect)) { continue; } /*** ABORT this iteration ***/ - srect = __intersect(&DefaultSrcClipRect, rsrc); /* Source clipping */ - - OffsetRect(&drect, disx, disy); /* Overlap and unscale for final combination */ - if (has_scaling) { - __scale_rect(&drect, srcwidth, dstwidth, srcheight, dstheight); - } - drect = srect = __intersect(&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)) { continue; } /*** ABORT this iteration ***/ + if (dwFlags & DDBLT_DDROPS) { + FIXME("\tDdraw Raster Ops: %08lx Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->u5.lpDDSPattern); } - } else { /* No clipper */ - if (rdst->left < DefaultDstClipRect.left || - rdst->top < DefaultDstClipRect.top || - rdst->right > DefaultDstClipRect.right || - rdst->bottom > DefaultDstClipRect.bottom) { continue; } /* ABORT this iteration */ - drect = *rdst; + /* Now the 'with source' blits */ if (src) { - if (rsrc->left < DefaultSrcClipRect.left || - rsrc->top < DefaultSrcClipRect.top || - rsrc->right > DefaultSrcClipRect.right || - rsrc->bottom > DefaultSrcClipRect.bottom) { continue; } /* ABORT this iteration */ - srect = *rsrc; - } - } /* clipper */ - - h = drect.bottom - drect.top; - w = drect.right - drect.left; - if (w<=0 || h<=0) { continue; } /*** ABORT this iteration ***/ - width = w*bpp; - - if (!src) { /* Source-less operations */ + LPBYTE sbase; + int sx, xinc, sy, yinc; - dbuf = (BYTE*)ddesc.lpSurface+(drect.top*ddesc.u1.lPitch)+(drect.left*bpp); + 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 & DDBLT_COLORFILL) { - ret = _Blt_ColorFill(dbuf, w, h, bpp, ddesc.u1.lPitch, fillcolor); - if (ret != DD_OK) { goto error; } /*** ERROR - ABORT ***/ + 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 */ + sbuf = sbase; + + /* check for overlapping surfaces */ + if (src != iface || xdst.top < xsrc.top || + xdst.right <= xsrc.left || xsrc.right <= xdst.left) + { + /* no overlap, or dst above src, so copy from top downwards */ + for (y = 0; y < dstheight; y++) + { + memcpy(dbuf, sbuf, width); + sbuf += sdesc.u1.lPitch; + dbuf += ddesc.u1.lPitch; } - /* 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); - if (ret != DD_OK) { goto error; } /*** ERROR - ABORT ***/ } - if (dwFlags & DDBLT_DDROPS) { - FIXME("\tDdraw Raster Ops: %08lx Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->u5.lpDDSPattern); - ret = DDERR_UNSUPPORTED; - goto error; /** UNSUPPORTED - ABORT ***/ + else if (xdst.top > xsrc.top) /* copy from bottom upwards */ + { + sbuf += (sdesc.u1.lPitch*dstheight); + dbuf += (ddesc.u1.lPitch*dstheight); + for (y = 0; y < dstheight; y++) + { + sbuf -= sdesc.u1.lPitch; + dbuf -= ddesc.u1.lPitch; + memcpy(dbuf, sbuf, width); } - - } else { /* Operations With Source */ - - 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) { /* copy without 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 row 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 = -spitch; - dpitch = -dpitch; } - for (y = 0; y < h; y++) { + else /* src and dst overlapping on the same line, use memmove */ + { + for (y = 0; y < dstheight; y++) + { memmove(dbuf, sbuf, width); - sbuf += spitch; - dbuf += dpitch; + sbuf += sdesc.u1.lPitch; + dbuf += ddesc.u1.lPitch; } - - } 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; } - } /* copy with colorkey */ - - } else { /* Copy with scaling */ - - LPBYTE sbase; - int sx, sy; - sbase = (BYTE*)sdesc.lpSurface+(srect.top*sdesc.u1.lPitch)+srect.left*bpp; - - if (!has_scolorkey) { /* copy without source color key */ - - if (dstwidth == srcwidth) { /* Stretching in Y direction only */ - for (y = sy = 0; y < h; y++, sy += yinc) { + } 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); + memcpy(dbuf, sbuf, width); dbuf += ddesc.u1.lPitch; } - - } else { /* Stretch all directions */ - + } + } else { + /* Stretching in X direction */ int last_sy = -1; - for (y = sy = 0; y < h; y++, sy += yinc) { + 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 { + /* this sourcerow is the same as last sourcerow - + * copy already stretched row + */ + memcpy(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) break; - case 2: STRETCH_ROW(WORD) break; - case 4: STRETCH_ROW(DWORD) break; - case 3: STRETCH_ROW_24 break; + 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]|(s[1]<<8)|(s[2]<<16); + d[0] = (pixel )&0xff; + d[1] = (pixel>> 8)&0xff; + d[2] = (pixel>>16)&0xff; + d+=3; + } + break; + } default: FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8); - ret = DDERR_UNSUPPORTED; goto error; + ret = DDERR_UNSUPPORTED; + goto error; } +#undef STRETCH_ROW } dbuf += ddesc.u1.lPitch; last_sy = sy; } - } /* stretch all directions */ + } + } else { + LONG dstyinc = ddesc.u1.lPitch, dstxinc = bpp; + DWORD keylow = 0, keyhigh = 0; + if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYDEST | DDBLT_KEYSRCOVERRIDE | DDBLT_KEYDESTOVERRIDE)) { - } else { /* copy with source color key (has_scolorkey) */ + if (dwFlags & DDBLT_KEYSRC) { + keylow = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue; + keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue; + } else if (dwFlags & DDBLT_KEYDEST){ + keylow = ddesc.ddckCKDestBlt.dwColorSpaceLowValue; + keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue; + } else if (dwFlags & DDBLT_KEYSRCOVERRIDE) { + keylow = lpbltfx->ddckSrcColorkey.dwColorSpaceLowValue; + keyhigh = lpbltfx->ddckSrcColorkey.dwColorSpaceHighValue; + } else { + keylow = lpbltfx->ddckDestColorkey.dwColorSpaceLowValue; + keyhigh = lpbltfx->ddckDestColorkey.dwColorSpaceHighValue; + } + dwFlags &= ~(DDBLT_KEYSRC | DDBLT_KEYDEST | DDBLT_KEYSRCOVERRIDE | DDBLT_KEYDESTOVERRIDE); + } - for (y = sy = 0; y < h; y++, sy += yinc) { - sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch; + if (dwFlags & DDBLT_DDFX) { + LPBYTE dTopLeft, dTopRight, dBottomLeft, dBottomRight, tmp; + LONG tmpxy; + dTopLeft = dbuf; + dTopRight = dbuf+((dstwidth-1)*bpp); + dBottomLeft = dTopLeft+((dstheight-1)*ddesc.u1.lPitch); + dBottomRight = dBottomLeft+((dstwidth-1)*bpp); + + if (lpbltfx->dwDDFX & DDBLTFX_ARITHSTRETCHY){ + /* I don't think we need to do anything about this flag */ + WARN("dwflags=DDBLT_DDFX nothing done for DDBLTFX_ARITHSTRETCHY\n"); + } + if (lpbltfx->dwDDFX & DDBLTFX_MIRRORLEFTRIGHT) { + tmp = dTopRight; + dTopRight = dTopLeft; + dTopLeft = tmp; + tmp = dBottomRight; + dBottomRight = dBottomLeft; + dBottomLeft = tmp; + dstxinc = dstxinc *-1; + } + if (lpbltfx->dwDDFX & DDBLTFX_MIRRORUPDOWN) { + tmp = dTopLeft; + dTopLeft = dBottomLeft; + dBottomLeft = tmp; + tmp = dTopRight; + dTopRight = dBottomRight; + dBottomRight = tmp; + dstyinc = dstyinc *-1; + } + if (lpbltfx->dwDDFX & DDBLTFX_NOTEARING) { + /* I don't think we need to do anything about this flag */ + WARN("dwflags=DDBLT_DDFX nothing done for DDBLTFX_NOTEARING\n"); + } + if (lpbltfx->dwDDFX & DDBLTFX_ROTATE180) { + tmp = dBottomRight; + dBottomRight = dTopLeft; + dTopLeft = tmp; + tmp = dBottomLeft; + dBottomLeft = dTopRight; + dTopRight = tmp; + dstxinc = dstxinc * -1; + dstyinc = dstyinc * -1; + } + if (lpbltfx->dwDDFX & DDBLTFX_ROTATE270) { + tmp = dTopLeft; + dTopLeft = dBottomLeft; + dBottomLeft = dBottomRight; + dBottomRight = dTopRight; + dTopRight = tmp; + tmpxy = dstxinc; + dstxinc = dstyinc; + dstyinc = tmpxy; + dstxinc = dstxinc * -1; + } + if (lpbltfx->dwDDFX & DDBLTFX_ROTATE90) { + tmp = dTopLeft; + dTopLeft = dTopRight; + dTopRight = dBottomRight; + dBottomRight = dBottomLeft; + dBottomLeft = tmp; + tmpxy = dstxinc; + dstxinc = dstyinc; + dstyinc = tmpxy; + dstyinc = dstyinc * -1; + } + if (lpbltfx->dwDDFX & DDBLTFX_ZBUFFERBASEDEST) { + /* I don't think we need to do anything about this flag */ + WARN("dwflags=DDBLT_DDFX nothing done for DDBLTFX_ZBUFFERBASEDEST\n"); + } + dbuf = dTopLeft; + dwFlags &= ~(DDBLT_DDFX); + } + +#define COPY_COLORKEY_FX(type) { \ + type *s = (type *) sbuf, *d = (type *) dbuf, *dx, tmp; \ + for (y = sy = 0; y < dstheight; y++, sy += yinc) { \ + (LPBYTE)s = sbase + (sy >> 16) * sdesc.u1.lPitch; \ + (LPBYTE)dx = d; \ + for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \ + tmp = s[sx >> 16]; \ + if (tmp < keylow || tmp > keyhigh) dx[0] = tmp; \ + (LPBYTE)dx += dstxinc; \ + } \ + (LPBYTE)d += dstyinc; \ + } \ + break; } switch (bpp) { - case 1: COPYROW_COLORKEY(BYTE) break; - case 2: COPYROW_COLORKEY(WORD) break; - case 4: COPYROW_COLORKEY(DWORD) break; + case 1: COPY_COLORKEY_FX(BYTE) + case 2: COPY_COLORKEY_FX(WORD) + case 4: COPY_COLORKEY_FX(DWORD) + case 3: {LPBYTE s,d = dbuf, dx; + for (y = sy = 0; y < dstheight; y++, sy += yinc) { + sbuf = sbase + (sy >> 16) * sdesc.u1.lPitch; + dx = d; + for (x = sx = 0; x < dstwidth; x++, sx+= xinc) { + DWORD pixel; + s = sbuf+3*(sx>>16); + pixel = s[0]|(s[1]<<8)|(s[2]<<16); + if (pixel < keylow || pixel > keyhigh){ + dx[0] = (pixel )&0xff; + dx[1] = (pixel>> 8)&0xff; + dx[2] = (pixel>>16)&0xff; + } + dx+= dstxinc; + } + d += dstyinc; + } + break;} default: - FIXME("Color-keyed blit not implemented for bpp %d!\n",bpp*8); + FIXME("%s color-keyed blit not implemented for bpp %d!\n", + (dwFlags & DDBLT_KEYSRC) ? "Source" : "Destination", bpp*8); ret = DDERR_UNSUPPORTED; goto error; +#undef COPY_COLORKEY_FX + } } - dbuf += ddesc.u1.lPitch; } - - } /* has_scolorkey */ - - } /* has_scaling */ - - } /* has_srccopy */ - } /* main loop ends */ error: -release: - - /* clear checked flags */ - if (dwFlags & DDBLT_COLORFILL) dwFlags &= ~DDBLT_COLORFILL; - if (dwFlags & DDBLT_DEPTHFILL) dwFlags &= ~DDBLT_DEPTHFILL; - if (dwFlags & DDBLT_DDROPS) dwFlags &= ~DDBLT_DDROPS; - if (dwFlags && FIXME_ON(ddraw)) { FIXME("\tUnsupported flags: "); DDRAW_dump_DDBLT(dwFlags); } - if (lpDstClipList) HeapFree(GetProcessHeap(), 0, lpDstClipList); - +release: IDirectDrawSurface7_Unlock(iface,NULL); if (src) IDirectDrawSurface7_Unlock(src,NULL); - return ret; + return DD_OK; } + #undef COPYBOX_COLORKEY #undef STRETCH_ROW #undef COPYROW_COLORKEY --=-fjHrW5KRGmT7HO6R7HAd--