📄 surface_gdi.c
字号:
if (Src == This)
{
int pitch;
UnionRect(&lock_union, &lock_src, &lock_dst);
/* Lock the union of the two rectangles */
ret = IWineD3DSurface_LockRect(iface, &dlock, &lock_union, 0);
if(ret != WINED3D_OK) goto error;
pitch = dlock.Pitch;
slock.Pitch = dlock.Pitch;
/* Since slock was originally copied from this surface's description, we can just reuse it */
assert(This->resource.allocatedMemory != NULL);
sbuf = (BYTE *)This->resource.allocatedMemory + lock_src.top * pitch + lock_src.left * bpp;
dbuf = (BYTE *)This->resource.allocatedMemory + lock_dst.top * pitch + lock_dst.left * bpp;
sEntry = getFormatDescEntry(Src->resource.format, NULL, NULL);
dEntry = sEntry;
}
else
{
ret = IWineD3DSurface_LockRect(Source, &slock, &lock_src, WINED3DLOCK_READONLY);
if(ret != WINED3D_OK) goto error;
ret = IWineD3DSurface_LockRect(iface, &dlock, &lock_dst, 0);
if(ret != WINED3D_OK) goto error;
sbuf = slock.pBits;
dbuf = dlock.pBits;
TRACE("Dst is at %p, Src is at %p\n", dbuf, sbuf);
sEntry = getFormatDescEntry(Src->resource.format, NULL, NULL);
dEntry = getFormatDescEntry(This->resource.format, NULL, NULL);
}
/* Handle first the FOURCC surfaces... */
if (sEntry->isFourcc && dEntry->isFourcc)
{
TRACE("Fourcc -> Fourcc copy\n");
if (trans)
FIXME("trans arg not supported when a FOURCC surface is involved\n");
if (dstx || dsty)
FIXME("offset for destination surface is not supported\n");
if (Src->resource.format != This->resource.format)
{
FIXME("FOURCC->FOURCC copy only supported for the same type of surface\n");
ret = WINED3DERR_WRONGTEXTUREFORMAT;
goto error;
}
/* FIXME: Watch out that the size is correct for FOURCC surfaces */
memcpy(dbuf, sbuf, This->resource.size);
goto error;
}
if (sEntry->isFourcc && !dEntry->isFourcc)
{
/* TODO: Use the libtxc_dxtn.so shared library to do
* software decompression
*/
ERR("DXTC decompression not supported by now\n");
goto error;
}
if (trans & (WINEDDBLTFAST_SRCCOLORKEY | WINEDDBLTFAST_DESTCOLORKEY))
{
DWORD keylow, keyhigh;
TRACE("Color keyed copy\n");
if (trans & WINEDDBLTFAST_SRCCOLORKEY)
{
keylow = Src->SrcBltCKey.dwColorSpaceLowValue;
keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
}
else
{
/* I'm not sure if this is correct */
FIXME("WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
keylow = This->DestBltCKey.dwColorSpaceLowValue;
keyhigh = This->DestBltCKey.dwColorSpaceHighValue;
}
#define COPYBOX_COLORKEY(type) { \
type *d, *s, tmp; \
s = (type *) sbuf; \
d = (type *) dbuf; \
for (y = 0; y < h; y++) { \
for (x = 0; x < w; x++) { \
tmp = s[x]; \
if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
} \
s = (type *)((BYTE *)s + slock.Pitch); \
d = (type *)((BYTE *)d + dlock.Pitch); \
} \
break; \
}
switch (bpp) {
case 1: COPYBOX_COLORKEY(BYTE)
case 2: COPYBOX_COLORKEY(WORD)
case 4: COPYBOX_COLORKEY(DWORD)
case 3:
{
BYTE *d, *s;
DWORD tmp;
s = (BYTE *) sbuf;
d = (BYTE *) dbuf;
for (y = 0; y < h; y++)
{
for (x = 0; x < w * 3; x += 3)
{
tmp = (DWORD)s[x] + ((DWORD)s[x + 1] << 8) + ((DWORD)s[x + 2] << 16);
if (tmp < keylow || tmp > keyhigh)
{
d[x + 0] = s[x + 0];
d[x + 1] = s[x + 1];
d[x + 2] = s[x + 2];
}
}
s += slock.Pitch;
d += dlock.Pitch;
}
break;
}
default:
FIXME("Source color key blitting not supported for bpp %d\n",bpp*8);
ret = WINED3DERR_NOTAVAILABLE;
goto error;
}
#undef COPYBOX_COLORKEY
TRACE("Copy Done\n");
}
else
{
int width = w * bpp;
TRACE("NO color key copy\n");
for (y = 0; y < h; y++)
{
/* This is pretty easy, a line for line memcpy */
memcpy(dbuf, sbuf, width);
sbuf += slock.Pitch;
dbuf += dlock.Pitch;
}
TRACE("Copy done\n");
}
error:
if (Src == This)
{
IWineD3DSurface_UnlockRect(iface);
}
else
{
IWineD3DSurface_UnlockRect(iface);
IWineD3DSurface_UnlockRect(Source);
}
return ret;
}
/*****************************************************************************
* IWineD3DSurface::LoadTexture, GDI version
*
* This is mutually unsupported by GDI surfaces
*
* Returns:
* D3DERR_INVALIDCALL
*
*****************************************************************************/
HRESULT WINAPI
IWineGDISurfaceImpl_LoadTexture(IWineD3DSurface *iface, BOOL srgb_mode)
{
ERR("Unsupported on X11 surfaces\n");
return WINED3DERR_INVALIDCALL;
}
/*****************************************************************************
* IWineD3DSurface::SaveSnapshot, GDI version
*
* This method writes the surface's contents to the in tga format to the
* file specified in filename.
*
* Params:
* filename: File to write to
*
* Returns:
* WINED3DERR_INVALIDCALL if the file couldn't be opened
* WINED3D_OK on success
*
*****************************************************************************/
static int get_shift(DWORD color_mask) {
int shift = 0;
while (color_mask > 0xFF) {
color_mask >>= 1;
shift += 1;
}
while ((color_mask & 0x80) == 0) {
color_mask <<= 1;
shift -= 1;
}
return shift;
}
HRESULT WINAPI
IWineGDISurfaceImpl_SaveSnapshot(IWineD3DSurface *iface,
const char* filename)
{
FILE* f = NULL;
UINT y = 0, x = 0;
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
static char *output = NULL;
static int size = 0;
const StaticPixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format, NULL, NULL);
if (This->pow2Width > size) {
output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pow2Width * 3);
size = This->pow2Width;
}
f = fopen(filename, "w+");
if (NULL == f) {
ERR("opening of %s failed with\n", filename);
return WINED3DERR_INVALIDCALL;
}
fprintf(f, "P6\n%d %d\n255\n", This->pow2Width, This->pow2Height);
if (This->resource.format == WINED3DFMT_P8) {
unsigned char table[256][3];
int i;
if (This->palette == NULL) {
fclose(f);
return WINED3DERR_INVALIDCALL;
}
for (i = 0; i < 256; i++) {
table[i][0] = This->palette->palents[i].peRed;
table[i][1] = This->palette->palents[i].peGreen;
table[i][2] = This->palette->palents[i].peBlue;
}
for (y = 0; y < This->pow2Height; y++) {
unsigned char *src = (unsigned char *) This->resource.allocatedMemory + (y * 1 * IWineD3DSurface_GetPitch(iface));
for (x = 0; x < This->pow2Width; x++) {
unsigned char color = *src;
src += 1;
output[3 * x + 0] = table[color][0];
output[3 * x + 1] = table[color][1];
output[3 * x + 2] = table[color][2];
}
fwrite(output, 3 * This->pow2Width, 1, f);
}
} else {
int red_shift, green_shift, blue_shift, pix_width;
pix_width = This->bytesPerPixel;
red_shift = get_shift(formatEntry->redMask);
green_shift = get_shift(formatEntry->greenMask);
blue_shift = get_shift(formatEntry->blueMask);
for (y = 0; y < This->pow2Height; y++) {
unsigned char *src = (unsigned char *) This->resource.allocatedMemory + (y * 1 * IWineD3DSurface_GetPitch(iface));
for (x = 0; x < This->pow2Width; x++) {
unsigned int color;
unsigned int comp;
int i;
color = 0;
for (i = 0; i < pix_width; i++) {
color |= src[i] << (8 * i);
}
src += 1 * pix_width;
comp = color & formatEntry->redMask;
output[3 * x + 0] = red_shift > 0 ? comp >> red_shift : comp << -red_shift;
comp = color & formatEntry->greenMask;
output[3 * x + 1] = green_shift > 0 ? comp >> green_shift : comp << -green_shift;
comp = color & formatEntry->blueMask;
output[3 * x + 2] = blue_shift > 0 ? comp >> blue_shift : comp << -blue_shift;
}
fwrite(output, 3 * This->pow2Width, 1, f);
}
}
fclose(f);
return WINED3D_OK;
}
/*****************************************************************************
* IWineD3DSurface::PrivateSetup, GDI version
*
* Initializes the GDI surface, aka creates the DIB section we render to
* The DIB section creation is done by calling GetDC, which will create the
* section and releasing the dc to allow the app to use it. The dib section
* will stay until the surface is released
*
* GDI surfaces do not need to be a power of 2 in size, so the pow2 sizes
* are set to the real sizes to save memory. The NONPOW2 flag is unset to
* avoid confusion in the shared surface code.
*
* Returns:
* WINED3D_OK on success
* The return values of called methods on failure
*
*****************************************************************************/
HRESULT WINAPI
IWineGDISurfaceImpl_PrivateSetup(IWineD3DSurface *iface)
{
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
HRESULT hr;
HDC hdc;
if(This->resource.usage & WINED3DUSAGE_OVERLAY)
{
ERR("(%p) Overlays not yet supported by GDI surfaces\n", This);
return WINED3DERR_INVALIDCALL;
}
/* Sysmem textures have memory already allocated -
* release it, this avoids an unnecessary memcpy
*/
HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
This->resource.allocatedMemory = NULL;
/* We don't mind the nonpow2 stuff in GDI */
This->pow2Width = This->currentDesc.Width;
This->pow2Height = This->currentDesc.Height;
/* Call GetDC to create a DIB section. We will use that
* DIB section for rendering
*
* Release the DC afterwards to allow the app to use it
*/
hr = IWineD3DSurface_GetDC(iface, &hdc);
if(FAILED(hr))
{
ERR("(%p) IWineD3DSurface::GetDC failed with hr %08x\n", This, hr);
return hr;
}
hr = IWineD3DSurface_ReleaseDC(iface, hdc);
if(FAILED(hr))
{
ERR("(%p) IWineD3DSurface::ReleaseDC failed with hr %08x\n", This, hr);
return hr;
}
return WINED3D_OK;
}
const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl =
{
/* IUnknown */
IWineD3DSurfaceImpl_QueryInterface,
IWineD3DSurfaceImpl_AddRef,
IWineD3DSurfaceImpl_Release,
/* IWineD3DResource */
IWineD3DSurfaceImpl_GetParent,
IWineD3DSurfaceImpl_GetDevice,
IWineD3DSurfaceImpl_SetPrivateData,
IWineD3DSurfaceImpl_GetPrivateData,
IWineD3DSurfaceImpl_FreePrivateData,
IWineD3DSurfaceImpl_SetPriority,
IWineD3DSurfaceImpl_GetPriority,
IWineGDISurfaceImpl_PreLoad,
IWineD3DSurfaceImpl_GetType,
/* IWineD3DSurface */
IWineD3DSurfaceImpl_GetContainer,
IWineD3DSurfaceImpl_GetDesc,
IWineGDISurfaceImpl_LockRect,
IWineGDISurfaceImpl_UnlockRect,
IWineD3DSurfaceImpl_GetDC,
IWineD3DSurfaceImpl_ReleaseDC,
IWineGDISurfaceImpl_Flip,
IWineGDISurfaceImpl_Blt,
IWineD3DSurfaceImpl_GetBltStatus,
IWineD3DSurfaceImpl_GetFlipStatus,
IWineD3DSurfaceImpl_IsLost,
IWineD3DSurfaceImpl_Restore,
IWineGDISurfaceImpl_BltFast,
IWineD3DSurfaceImpl_GetPalette,
IWineD3DSurfaceImpl_SetPalette,
IWineD3DSurfaceImpl_RealizePalette,
IWineD3DSurfaceImpl_SetColorKey,
IWineD3DSurfaceImpl_GetPitch,
IWineD3DSurfaceImpl_SetMem,
IWineD3DSurfaceImpl_SetOverlayPosition,
IWineD3DSurfaceImpl_GetOverlayPosition,
IWineD3DSurfaceImpl_UpdateOverlayZOrder,
IWineD3DSurfaceImpl_UpdateOverlay,
IWineD3DSurfaceImpl_SetClipper,
IWineD3DSurfaceImpl_GetClipper,
/* Internal use: */
IWineD3DSurfaceImpl_AddDirtyRect,
IWineGDISurfaceImpl_LoadTexture,
IWineGDISurfaceImpl_SaveSnapshot,
IWineD3DSurfaceImpl_SetContainer,
IWineD3DSurfaceImpl_SetGlTextureDesc,
IWineD3DSurfaceImpl_GetGlDesc,
IWineD3DSurfaceImpl_GetData,
IWineD3DSurfaceImpl_SetFormat,
IWineGDISurfaceImpl_PrivateSetup
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -