mirror of
https://github.com/reactos/wine.git
synced 2025-02-12 23:58:56 +00:00
- add S3TC support to BltFast (fixes NOLF)
- proper surface unlocking in case of error in the Blt case
This commit is contained in:
parent
1866dfbe16
commit
fbf003dd39
@ -359,26 +359,132 @@ static HRESULT _Blt_ColorFill(
|
|||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComputeShifts(DWORD mask, DWORD* lshift, DWORD* rshift)
|
static void ComputeShifts(DWORD mask, DWORD* lshift, DWORD* rshift)
|
||||||
{
|
{
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
int bits = 0;
|
int bits = 0;
|
||||||
*lshift = 0;
|
*lshift = 0;
|
||||||
*rshift = 0;
|
*rshift = 0;
|
||||||
|
|
||||||
if (!mask)
|
if (!mask)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while(!(mask & (1 << pos)))
|
while(!(mask & (1 << pos)))
|
||||||
pos++;
|
pos++;
|
||||||
|
|
||||||
while(mask & (1 << (pos+bits)))
|
while(mask & (1 << (pos+bits)))
|
||||||
bits++;
|
bits++;
|
||||||
|
|
||||||
*lshift = pos;
|
*lshift = pos;
|
||||||
*rshift = 8 - bits;
|
*rshift = 8 - bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is used to factorize the decompression between the Blt and BltFast code */
|
||||||
|
static void DoDXTCDecompression(const DDSURFACEDESC2 *sdesc, const DDSURFACEDESC2 *ddesc)
|
||||||
|
{
|
||||||
|
DWORD rs,rb,rm;
|
||||||
|
DWORD gs,gb,gm;
|
||||||
|
DWORD bs,bb,bm;
|
||||||
|
DWORD as,ab,am;
|
||||||
|
|
||||||
|
if (!s3tc_initialized) {
|
||||||
|
/* FIXME: We may fake this by rendering the texture into the framebuffer using OpenGL functions and reading back
|
||||||
|
* the framebuffer. This will be slow and somewhat ugly. */
|
||||||
|
FIXME("Manual S3TC decompression is not supported in native mode\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rm = ddesc->u4.ddpfPixelFormat.u2.dwRBitMask;
|
||||||
|
ComputeShifts(rm, &rs, &rb);
|
||||||
|
gm = ddesc->u4.ddpfPixelFormat.u3.dwGBitMask;
|
||||||
|
ComputeShifts(gm, &gs, &gb);
|
||||||
|
bm = ddesc->u4.ddpfPixelFormat.u4.dwBBitMask;
|
||||||
|
ComputeShifts(bm, &bs, &bb);
|
||||||
|
am = ddesc->u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask;
|
||||||
|
ComputeShifts(am, &as, &ab);
|
||||||
|
if (sdesc->u4.ddpfPixelFormat.dwFourCC == MAKE_FOURCC('D','X','T','1')) {
|
||||||
|
int is16 = ddesc->u4.ddpfPixelFormat.u1.dwRGBBitCount == 16;
|
||||||
|
int pitch = ddesc->u1.lPitch;
|
||||||
|
int width = ddesc->dwWidth;
|
||||||
|
int height = ddesc->dwHeight;
|
||||||
|
int x,y;
|
||||||
|
char* dst = (char*) ddesc->lpSurface;
|
||||||
|
char* src = (char*) sdesc->lpSurface;
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
for (y =0; y < height; y++) {
|
||||||
|
DWORD pixel = 0;
|
||||||
|
BYTE data[4];
|
||||||
|
(*fetch_2d_texel_rgba_dxt1)(width, src, x, y, data);
|
||||||
|
pixel = 0;
|
||||||
|
pixel |= ((data[0] >> rb) << rs) & rm;
|
||||||
|
pixel |= ((data[1] >> gb) << gs) & gm;
|
||||||
|
pixel |= ((data[2] >> bb) << bs) & bm;
|
||||||
|
pixel |= ((data[3] >> ab) << as) & am;
|
||||||
|
if (is16)
|
||||||
|
*((WORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
||||||
|
else
|
||||||
|
*((DWORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
||||||
|
}
|
||||||
|
} else if (sdesc->u4.ddpfPixelFormat.dwFourCC == MAKE_FOURCC('D','X','T','3')) {
|
||||||
|
int is16 = ddesc->u4.ddpfPixelFormat.u1.dwRGBBitCount == 16;
|
||||||
|
int pitch = ddesc->u1.lPitch;
|
||||||
|
int width = ddesc->dwWidth;
|
||||||
|
int height = ddesc->dwHeight;
|
||||||
|
int x,y;
|
||||||
|
char* dst = (char*) ddesc->lpSurface;
|
||||||
|
char* src = (char*) sdesc->lpSurface;
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
for (y =0; y < height; y++) {
|
||||||
|
DWORD pixel = 0;
|
||||||
|
BYTE data[4];
|
||||||
|
(*fetch_2d_texel_rgba_dxt3)(width, src, x, y, data);
|
||||||
|
pixel = 0;
|
||||||
|
pixel |= ((data[0] >> rb) << rs) & rm;
|
||||||
|
pixel |= ((data[1] >> gb) << gs) & gm;
|
||||||
|
pixel |= ((data[2] >> bb) << bs) & bm;
|
||||||
|
pixel |= ((data[3] >> ab) << as) & am;
|
||||||
|
if (is16)
|
||||||
|
*((WORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
||||||
|
else
|
||||||
|
*((DWORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
||||||
|
}
|
||||||
|
} else if (sdesc->u4.ddpfPixelFormat.dwFourCC == MAKE_FOURCC('D','X','T','5')) {
|
||||||
|
int is16 = ddesc->u4.ddpfPixelFormat.u1.dwRGBBitCount == 16;
|
||||||
|
int pitch = ddesc->u1.lPitch;
|
||||||
|
int width = ddesc->dwWidth;
|
||||||
|
int height = ddesc->dwHeight;
|
||||||
|
int x,y;
|
||||||
|
char* dst = (char*) ddesc->lpSurface;
|
||||||
|
char* src = (char*) sdesc->lpSurface;
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
for (y =0; y < height; y++) {
|
||||||
|
DWORD pixel = 0;
|
||||||
|
BYTE data[4];
|
||||||
|
(*fetch_2d_texel_rgba_dxt5)(width, src, x, y, data);
|
||||||
|
pixel = 0;
|
||||||
|
pixel |= ((data[0] >> rb) << rs) & rm;
|
||||||
|
pixel |= ((data[1] >> gb) << gs) & gm;
|
||||||
|
pixel |= ((data[2] >> bb) << bs) & bm;
|
||||||
|
pixel |= ((data[3] >> ab) << as) & am;
|
||||||
|
if (is16)
|
||||||
|
*((WORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
||||||
|
else
|
||||||
|
*((DWORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if 0 /* Usefull for debugging */
|
||||||
|
{
|
||||||
|
static int idx;
|
||||||
|
char texname[255];
|
||||||
|
FILE* f;
|
||||||
|
sprintf(texname, "dxt_%d.pnm", idx++);
|
||||||
|
f = fopen(texname,"w");
|
||||||
|
DDRAW_dump_surface_to_disk(This, f, 1);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT WINAPI
|
HRESULT WINAPI
|
||||||
DIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst,
|
DIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst,
|
||||||
LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
|
LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
|
||||||
@ -391,7 +497,7 @@ DIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst,
|
|||||||
int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
|
int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
|
||||||
int x, y;
|
int x, y;
|
||||||
LPBYTE dbuf, sbuf;
|
LPBYTE dbuf, sbuf;
|
||||||
|
|
||||||
TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
|
TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
|
||||||
|
|
||||||
if (TRACE_ON(ddraw)) {
|
if (TRACE_ON(ddraw)) {
|
||||||
@ -422,7 +528,8 @@ DIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst,
|
|||||||
(ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)) {
|
(ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)) {
|
||||||
if (sdesc.u4.ddpfPixelFormat.dwFourCC != sdesc.u4.ddpfPixelFormat.dwFourCC) {
|
if (sdesc.u4.ddpfPixelFormat.dwFourCC != sdesc.u4.ddpfPixelFormat.dwFourCC) {
|
||||||
FIXME("FOURCC->FOURCC copy only supported for the same type of surface\n");
|
FIXME("FOURCC->FOURCC copy only supported for the same type of surface\n");
|
||||||
return DDERR_INVALIDPIXELFORMAT;
|
ret = DDERR_INVALIDPIXELFORMAT;
|
||||||
|
goto release;
|
||||||
}
|
}
|
||||||
memcpy(ddesc.lpSurface, sdesc.lpSurface, ddesc.u1.dwLinearSize);
|
memcpy(ddesc.lpSurface, sdesc.lpSurface, ddesc.u1.dwLinearSize);
|
||||||
goto release;
|
goto release;
|
||||||
@ -430,107 +537,7 @@ DIB_DirectDrawSurface_Blt(LPDIRECTDRAWSURFACE7 iface, LPRECT rdst,
|
|||||||
|
|
||||||
if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
|
if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
|
||||||
(!(ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC))) {
|
(!(ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC))) {
|
||||||
DWORD rs,rb,rm;
|
DoDXTCDecompression(&sdesc, &ddesc);
|
||||||
DWORD gs,gb,gm;
|
|
||||||
DWORD bs,bb,bm;
|
|
||||||
DWORD as,ab,am;
|
|
||||||
|
|
||||||
if (!s3tc_initialized) {
|
|
||||||
/* FIXME: We may fake this by rendering the texture into the framebuffer using OpenGL functions and reading back
|
|
||||||
* the framebuffer. This will be slow and somewhat ugly. */
|
|
||||||
FIXME("Manual S3TC decompression is not supported in native mode\n");
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
|
|
||||||
rm = ddesc.u4.ddpfPixelFormat.u2.dwRBitMask;
|
|
||||||
ComputeShifts(rm, &rs, &rb);
|
|
||||||
gm = ddesc.u4.ddpfPixelFormat.u3.dwGBitMask;
|
|
||||||
ComputeShifts(gm, &gs, &gb);
|
|
||||||
bm = ddesc.u4.ddpfPixelFormat.u4.dwBBitMask;
|
|
||||||
ComputeShifts(bm, &bs, &bb);
|
|
||||||
am = ddesc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask;
|
|
||||||
ComputeShifts(am, &as, &ab);
|
|
||||||
if (sdesc.u4.ddpfPixelFormat.dwFourCC == MAKE_FOURCC('D','X','T','1')) {
|
|
||||||
int is16 = ddesc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16;
|
|
||||||
int pitch = ddesc.u1.lPitch;
|
|
||||||
int width = ddesc.dwWidth;
|
|
||||||
int height = ddesc.dwHeight;
|
|
||||||
int x,y;
|
|
||||||
char* dst = (char*) ddesc.lpSurface;
|
|
||||||
char* src = (char*) sdesc.lpSurface;
|
|
||||||
for (x = 0; x < width; x++)
|
|
||||||
for (y =0; y < height; y++) {
|
|
||||||
DWORD pixel = 0;
|
|
||||||
BYTE data[4];
|
|
||||||
(*fetch_2d_texel_rgba_dxt1)(width, src, x, y, data);
|
|
||||||
pixel = 0;
|
|
||||||
pixel |= ((data[0] >> rb) << rs) & rm;
|
|
||||||
pixel |= ((data[1] >> gb) << gs) & gm;
|
|
||||||
pixel |= ((data[2] >> bb) << bs) & bm;
|
|
||||||
pixel |= ((data[3] >> ab) << as) & am;
|
|
||||||
if (is16)
|
|
||||||
*((WORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
|
||||||
else
|
|
||||||
*((DWORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
|
||||||
}
|
|
||||||
} else if (sdesc.u4.ddpfPixelFormat.dwFourCC == MAKE_FOURCC('D','X','T','3')) {
|
|
||||||
int is16 = ddesc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16;
|
|
||||||
int pitch = ddesc.u1.lPitch;
|
|
||||||
int width = ddesc.dwWidth;
|
|
||||||
int height = ddesc.dwHeight;
|
|
||||||
int x,y;
|
|
||||||
char* dst = (char*) ddesc.lpSurface;
|
|
||||||
char* src = (char*) sdesc.lpSurface;
|
|
||||||
for (x = 0; x < width; x++)
|
|
||||||
for (y =0; y < height; y++) {
|
|
||||||
DWORD pixel = 0;
|
|
||||||
BYTE data[4];
|
|
||||||
(*fetch_2d_texel_rgba_dxt3)(width, src, x, y, data);
|
|
||||||
pixel = 0;
|
|
||||||
pixel |= ((data[0] >> rb) << rs) & rm;
|
|
||||||
pixel |= ((data[1] >> gb) << gs) & gm;
|
|
||||||
pixel |= ((data[2] >> bb) << bs) & bm;
|
|
||||||
pixel |= ((data[3] >> ab) << as) & am;
|
|
||||||
if (is16)
|
|
||||||
*((WORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
|
||||||
else
|
|
||||||
*((DWORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
|
||||||
}
|
|
||||||
} else if (sdesc.u4.ddpfPixelFormat.dwFourCC == MAKE_FOURCC('D','X','T','5')) {
|
|
||||||
int is16 = ddesc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16;
|
|
||||||
int pitch = ddesc.u1.lPitch;
|
|
||||||
int width = ddesc.dwWidth;
|
|
||||||
int height = ddesc.dwHeight;
|
|
||||||
int x,y;
|
|
||||||
char* dst = (char*) ddesc.lpSurface;
|
|
||||||
char* src = (char*) sdesc.lpSurface;
|
|
||||||
for (x = 0; x < width; x++)
|
|
||||||
for (y =0; y < height; y++) {
|
|
||||||
DWORD pixel = 0;
|
|
||||||
BYTE data[4];
|
|
||||||
(*fetch_2d_texel_rgba_dxt5)(width, src, x, y, data);
|
|
||||||
pixel = 0;
|
|
||||||
pixel |= ((data[0] >> rb) << rs) & rm;
|
|
||||||
pixel |= ((data[1] >> gb) << gs) & gm;
|
|
||||||
pixel |= ((data[2] >> bb) << bs) & bm;
|
|
||||||
pixel |= ((data[3] >> ab) << as) & am;
|
|
||||||
if (is16)
|
|
||||||
*((WORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
|
||||||
else
|
|
||||||
*((DWORD*)(dst+y*pitch+x*(is16?2:4))) = pixel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if 0 /* Usefull for debugging */
|
|
||||||
{
|
|
||||||
static int idx;
|
|
||||||
char texname[255];
|
|
||||||
FILE* f;
|
|
||||||
sprintf(texname, "dxt_%d.pnm", idx++);
|
|
||||||
f = fopen(texname,"w");
|
|
||||||
DDRAW_dump_surface_to_disk(This, f, 1);
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
goto release;
|
goto release;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -984,14 +991,6 @@ DIB_DirectDrawSurface_BltFast(LPDIRECTDRAWSURFACE7 iface, DWORD dstx,
|
|||||||
ddesc = This->surface_desc;
|
ddesc = This->surface_desc;
|
||||||
sdesc = (ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src))->surface_desc;
|
sdesc = (ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src))->surface_desc;
|
||||||
|
|
||||||
if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) && (ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)) {
|
|
||||||
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");
|
|
||||||
DIB_DirectDrawSurface_Blt(iface, NULL, src, rsrc, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rsrc) {
|
if (!rsrc) {
|
||||||
WARN("rsrc is NULL!\n");
|
WARN("rsrc is NULL!\n");
|
||||||
rsrc = &rsrc2;
|
rsrc = &rsrc2;
|
||||||
@ -1027,6 +1026,26 @@ DIB_DirectDrawSurface_BltFast(LPDIRECTDRAWSURFACE7 iface, DWORD dstx,
|
|||||||
ddesc.dwSize = sizeof(ddesc);
|
ddesc.dwSize = sizeof(ddesc);
|
||||||
IDirectDrawSurface7_Lock(iface, &lock_dst, &ddesc, DDLOCK_WRITEONLY, 0);
|
IDirectDrawSurface7_Lock(iface, &lock_dst, &ddesc, DDLOCK_WRITEONLY, 0);
|
||||||
|
|
||||||
|
/* Handle first the FOURCC surfaces... */
|
||||||
|
if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) && (ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)) {
|
||||||
|
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 (sdesc.u4.ddpfPixelFormat.dwFourCC != sdesc.u4.ddpfPixelFormat.dwFourCC) {
|
||||||
|
FIXME("FOURCC->FOURCC copy only supported for the same type of surface\n");
|
||||||
|
ret = DDERR_INVALIDPIXELFORMAT;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
memcpy(ddesc.lpSurface, sdesc.lpSurface, ddesc.u1.dwLinearSize);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
|
||||||
|
(!(ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC))) {
|
||||||
|
DoDXTCDecompression(&sdesc, &ddesc);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
bpp = GET_BPP(This->surface_desc);
|
bpp = GET_BPP(This->surface_desc);
|
||||||
sbuf = (BYTE *) sdesc.lpSurface;
|
sbuf = (BYTE *) sdesc.lpSurface;
|
||||||
dbuf = (BYTE *) ddesc.lpSurface;
|
dbuf = (BYTE *) ddesc.lpSurface;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user