⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 surface_gdi.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
                {
                    /* 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 + -