📄 surface_gdi.c
字号:
{
/* No stretching in either direction. This needs to be as
* fast as possible */
sbuf = sbase;
/* check for overlapping surfaces */
if (SrcSurface != 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 += slock.Pitch;
dbuf += dlock.Pitch;
}
}
else if (xdst.top > xsrc.top) /* copy from bottom upwards */
{
sbuf += (slock.Pitch*dstheight);
dbuf += (dlock.Pitch*dstheight);
for (y = 0; y < dstheight; y++)
{
sbuf -= slock.Pitch;
dbuf -= dlock.Pitch;
memcpy(dbuf, sbuf, width);
}
}
else /* src and dst overlapping on the same line, use memmove */
{
for (y = 0; y < dstheight; y++)
{
memmove(dbuf, sbuf, width);
sbuf += slock.Pitch;
dbuf += dlock.Pitch;
}
}
} else {
/* Stretching in Y direction only */
for (y = sy = 0; y < dstheight; y++, sy += yinc) {
sbuf = sbase + (sy >> 16) * slock.Pitch;
memcpy(dbuf, sbuf, width);
dbuf += dlock.Pitch;
}
}
}
else
{
/* Stretching in X direction */
int last_sy = -1;
for (y = sy = 0; y < dstheight; y++, sy += yinc)
{
sbuf = sbase + (sy >> 16) * slock.Pitch;
if ((sy >> 16) == (last_sy >> 16))
{
/* this sourcerow is the same as last sourcerow -
* copy already stretched row
*/
memcpy(dbuf, dbuf - dlock.Pitch, 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]|(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 = WINED3DERR_NOTAVAILABLE;
goto error;
}
#undef STRETCH_ROW
}
dbuf += dlock.Pitch;
last_sy = sy;
}
}
}
else
{
LONG dstyinc = dlock.Pitch, dstxinc = bpp;
DWORD keylow = 0xFFFFFFFF, keyhigh = 0, keymask = 0xFFFFFFFF;
DWORD destkeylow = 0x0, destkeyhigh = 0xFFFFFFFF, destkeymask = 0xFFFFFFFF;
if (Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE))
{
/* The color keying flags are checked for correctness in ddraw */
if (Flags & WINEDDBLT_KEYSRC)
{
keylow = Src->SrcBltCKey.dwColorSpaceLowValue;
keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
}
else if (Flags & WINEDDBLT_KEYSRCOVERRIDE)
{
keylow = DDBltFx->ddckSrcColorkey.dwColorSpaceLowValue;
keyhigh = DDBltFx->ddckSrcColorkey.dwColorSpaceHighValue;
}
if (Flags & WINEDDBLT_KEYDEST)
{
/* Destination color keys are taken from the source surface ! */
destkeylow = Src->DestBltCKey.dwColorSpaceLowValue;
destkeyhigh = Src->DestBltCKey.dwColorSpaceHighValue;
}
else if (Flags & WINEDDBLT_KEYDESTOVERRIDE)
{
destkeylow = DDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
destkeyhigh = DDBltFx->ddckDestColorkey.dwColorSpaceHighValue;
}
if(bpp == 1)
{
keymask = 0xff;
}
else
{
keymask = sEntry->redMask |
sEntry->greenMask |
sEntry->blueMask;
}
Flags &= ~(WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE);
}
if (Flags & WINEDDBLT_DDFX)
{
LPBYTE dTopLeft, dTopRight, dBottomLeft, dBottomRight, tmp;
LONG tmpxy;
dTopLeft = dbuf;
dTopRight = dbuf+((dstwidth-1)*bpp);
dBottomLeft = dTopLeft+((dstheight-1)*dlock.Pitch);
dBottomRight = dBottomLeft+((dstwidth-1)*bpp);
if (DDBltFx->dwDDFX & WINEDDBLTFX_ARITHSTRETCHY)
{
/* I don't think we need to do anything about this flag */
WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n");
}
if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORLEFTRIGHT)
{
tmp = dTopRight;
dTopRight = dTopLeft;
dTopLeft = tmp;
tmp = dBottomRight;
dBottomRight = dBottomLeft;
dBottomLeft = tmp;
dstxinc = dstxinc *-1;
}
if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORUPDOWN)
{
tmp = dTopLeft;
dTopLeft = dBottomLeft;
dBottomLeft = tmp;
tmp = dTopRight;
dTopRight = dBottomRight;
dBottomRight = tmp;
dstyinc = dstyinc *-1;
}
if (DDBltFx->dwDDFX & WINEDDBLTFX_NOTEARING)
{
/* I don't think we need to do anything about this flag */
WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n");
}
if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE180)
{
tmp = dBottomRight;
dBottomRight = dTopLeft;
dTopLeft = tmp;
tmp = dBottomLeft;
dBottomLeft = dTopRight;
dTopRight = tmp;
dstxinc = dstxinc * -1;
dstyinc = dstyinc * -1;
}
if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE270)
{
tmp = dTopLeft;
dTopLeft = dBottomLeft;
dBottomLeft = dBottomRight;
dBottomRight = dTopRight;
dTopRight = tmp;
tmpxy = dstxinc;
dstxinc = dstyinc;
dstyinc = tmpxy;
dstxinc = dstxinc * -1;
}
if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE90)
{
tmp = dTopLeft;
dTopLeft = dTopRight;
dTopRight = dBottomRight;
dBottomRight = dBottomLeft;
dBottomLeft = tmp;
tmpxy = dstxinc;
dstxinc = dstyinc;
dstyinc = tmpxy;
dstyinc = dstyinc * -1;
}
if (DDBltFx->dwDDFX & WINEDDBLTFX_ZBUFFERBASEDEST)
{
/* I don't think we need to do anything about this flag */
WARN("Flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n");
}
dbuf = dTopLeft;
Flags &= ~(WINEDDBLT_DDFX);
}
#define COPY_COLORKEY_FX(type) { \
type *s, *d = (type *) dbuf, *dx, tmp; \
for (y = sy = 0; y < dstheight; y++, sy += yinc) { \
s = (type*)(sbase + (sy >> 16) * slock.Pitch); \
dx = d; \
for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
tmp = s[sx >> 16]; \
if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
dx[0] = tmp; \
} \
dx = (type*)(((LPBYTE)dx)+dstxinc); \
} \
d = (type*)(((LPBYTE)d)+dstyinc); \
} \
break; }
switch (bpp) {
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) * slock.Pitch;
dx = d;
for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
{
DWORD pixel, dpixel = 0;
s = sbuf+3*(sx>>16);
pixel = s[0]|(s[1]<<8)|(s[2]<<16);
dpixel = dx[0]|(dx[1]<<8)|(dx[2]<<16);
if (((pixel & keymask) < keylow || (pixel & keymask) > keyhigh) &&
((dpixel & keymask) >= destkeylow || (dpixel & keymask) <= keyhigh))
{
dx[0] = (pixel )&0xff;
dx[1] = (pixel>> 8)&0xff;
dx[2] = (pixel>>16)&0xff;
}
dx+= dstxinc;
}
d += dstyinc;
}
break;
}
default:
FIXME("%s color-keyed blit not implemented for bpp %d!\n",
(Flags & WINEDDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
ret = WINED3DERR_NOTAVAILABLE;
goto error;
#undef COPY_COLORKEY_FX
}
}
}
error:
if (Flags && FIXME_ON(d3d_surface))
{
FIXME("\tUnsupported flags: %08x\n", Flags);
}
release:
IWineD3DSurface_UnlockRect(iface);
if (SrcSurface && SrcSurface != iface) IWineD3DSurface_UnlockRect(SrcSurface);
return ret;
}
/*****************************************************************************
* IWineD3DSurface::BltFast, GDI version
*
* This is the software implementation of BltFast, as used by GDI surfaces
* and as a fallback for OpenGL surfaces. This code is taken from the old
* DirectDraw code, and was originally written by TransGaming.
*
* Params:
* dstx:
* dsty:
* Source: Source surface to copy from
* rsrc: Source rectangle
* trans: Some Flags
*
* Returns:
* WINED3D_OK on success
*
*****************************************************************************/
HRESULT WINAPI
IWineGDISurfaceImpl_BltFast(IWineD3DSurface *iface,
DWORD dstx,
DWORD dsty,
IWineD3DSurface *Source,
RECT *rsrc,
DWORD trans)
{
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) Source;
int bpp, w, h, x, y;
WINED3DLOCKED_RECT dlock,slock;
HRESULT ret = WINED3D_OK;
RECT rsrc2;
RECT lock_src, lock_dst, lock_union;
BYTE *sbuf, *dbuf;
const StaticPixelFormatDesc *sEntry, *dEntry;
if (TRACE_ON(d3d_surface))
{
TRACE("(%p)->(%d,%d,%p,%p,%08x)\n", This,dstx,dsty,Src,rsrc,trans);
if (rsrc)
{
TRACE("\tsrcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,
rsrc->right,rsrc->bottom);
}
else
{
TRACE(" srcrect: NULL\n");
}
}
if ((This->Flags & SFLAG_LOCKED) ||
((Src != NULL) && (Src->Flags & SFLAG_LOCKED)))
{
WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
return WINEDDERR_SURFACEBUSY;
}
if (!rsrc)
{
WARN("rsrc is NULL!\n");
rsrc = &rsrc2;
rsrc->left = 0;
rsrc->top = 0;
rsrc->right = Src->currentDesc.Width;
rsrc->bottom = Src->currentDesc.Height;
}
/* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/
if ((rsrc->bottom > Src->currentDesc.Height) || (rsrc->bottom < 0) ||
(rsrc->top > Src->currentDesc.Height) || (rsrc->top < 0) ||
(rsrc->left > Src->currentDesc.Width) || (rsrc->left < 0) ||
(rsrc->right > Src->currentDesc.Width) || (rsrc->right < 0) ||
(rsrc->right < rsrc->left) || (rsrc->bottom < rsrc->top))
{
WARN("Application gave us bad source rectangle for BltFast.\n");
return WINEDDERR_INVALIDRECT;
}
h = rsrc->bottom - rsrc->top;
if (h > This->currentDesc.Height-dsty) h = This->currentDesc.Height-dsty;
if (h > Src->currentDesc.Height-rsrc->top) h=Src->currentDesc.Height-rsrc->top;
if (h <= 0) return WINEDDERR_INVALIDRECT;
w = rsrc->right - rsrc->left;
if (w > This->currentDesc.Width-dstx) w = This->currentDesc.Width-dstx;
if (w > Src->currentDesc.Width-rsrc->left) w = Src->currentDesc.Width-rsrc->left;
if (w <= 0) return WINEDDERR_INVALIDRECT;
/* Now compute the locking rectangle... */
lock_src.left = rsrc->left;
lock_src.top = rsrc->top;
lock_src.right = lock_src.left + w;
lock_src.bottom = lock_src.top + h;
lock_dst.left = dstx;
lock_dst.top = dsty;
lock_dst.right = dstx + w;
lock_dst.bottom = dsty + h;
bpp = This->bytesPerPixel;
/* We need to lock the surfaces, or we won't get refreshes when done. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -