blob: d5843e136e14a685a90d7bdb45fdbf5324af0c21 [file] [log] [blame]
/* DirectDrawSurface base implementation
*
* Copyright 1997-2000 Marcus Meissner
* Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
*/
#include "config.h"
#include "winerror.h"
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "debugtools.h"
#include "bitmap.h"
#include "ddraw_private.h"
DEFAULT_DEBUG_CHANNEL(ddraw);
/******************************************************************************
* IDirectDrawSurface methods
*
* Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
* DDS and DDS2 use those functions. (Function calls did not change (except
* using different DirectDrawSurfaceX version), just added flags and functions)
*/
HRESULT WINAPI IDirectDrawSurface4Impl_Lock(
LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
This,lprect,lpddsd,flags,(DWORD)hnd);
/* DO NOT AddRef the surface! Lock/Unlock must not come in matched pairs
* -Marcus Meissner 20000509
*/
if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
This,lprect,lpddsd,flags,(DWORD)hnd);
/* First, copy the Surface description */
*lpddsd = This->s.surface_desc;
TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
/* If asked only for a part, change the surface pointer */
if (lprect) {
TRACE(" lprect: %dx%d-%dx%d\n",
lprect->top,lprect->left,lprect->bottom,lprect->right
);
if ((lprect->top < 0) ||
(lprect->left < 0) ||
(lprect->bottom < 0) ||
(lprect->right < 0)) {
ERR(" Negative values in LPRECT !!!\n");
return DDERR_INVALIDPARAMS;
}
lpddsd->u1.lpSurface = (LPVOID) ((char *) This->s.surface_desc.u1.lpSurface +
(lprect->top*This->s.surface_desc.lPitch) +
lprect->left*GET_BPP(This->s.surface_desc));
} else {
assert(This->s.surface_desc.u1.lpSurface);
}
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_Unlock(
LPDIRECTDRAWSURFACE4 iface,LPVOID surface
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
/* DO NOT Release the surface! Lock/Unlock MUST NOT come in matched pairs
* Marcus Meissner 20000509
*/
TRACE("(%p)->Unlock(%p)\n",This,surface);
return DD_OK;
}
IDirectDrawSurface4Impl* _common_find_flipto(
IDirectDrawSurface4Impl* This,IDirectDrawSurface4Impl* flipto
) {
int i,j,flipable=0;
struct _surface_chain *chain = This->s.chain;
if (!chain) {
ERR("No flip chain? -> returning This.\n");
return This;
}
/* if there was no override flipto, look for current backbuffer */
if (!flipto) {
/* walk the flip chain looking for backbuffer */
for (i=0;i<chain->nrofsurfaces;i++) {
if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FLIP)
flipable++;
if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_BACKBUFFER)
flipto = chain->surfaces[i];
}
/* sanity checks ... */
if (!flipto) {
if (flipable>1) {
for (i=0;i<chain->nrofsurfaces;i++)
if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FRONTBUFFER)
break;
if (i==chain->nrofsurfaces) {
/* we do not have a frontbuffer either */
for (i=0;i<chain->nrofsurfaces;i++)
if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FLIP) {
SDDSCAPS(chain->surfaces[i])|=DDSCAPS_FRONTBUFFER;
break;
}
for (j=i+1;j<i+chain->nrofsurfaces+1;j++) {
int k = j % chain->nrofsurfaces;
if (SDDSCAPS(chain->surfaces[k]) & DDSCAPS_FLIP) {
SDDSCAPS(chain->surfaces[k])|=DDSCAPS_BACKBUFFER;
flipto = chain->surfaces[k];
break;
}
}
}
}
if (!flipto)
flipto = This;
}
TRACE("flipping to %p\n",flipto);
}
return flipto;
}
static HRESULT _Blt_ColorFill(
LPBYTE buf, int width, int height, int bpp, LONG lPitch, DWORD color
) {
int x, y;
LPBYTE first;
/* Do first row */
#define COLORFILL_ROW(type) { \
type *d = (type *) buf; \
for (x = 0; x < width; x++) \
d[x] = (type) color; \
break; \
}
switch(bpp) {
case 1: COLORFILL_ROW(BYTE)
case 2: COLORFILL_ROW(WORD)
case 4: COLORFILL_ROW(DWORD)
default:
FIXME("Color fill not implemented for bpp %d!\n", bpp*8);
return DDERR_UNSUPPORTED;
}
#undef COLORFILL_ROW
/* Now copy first row */
first = buf;
for (y = 1; y < height; y++) {
buf += lPitch;
memcpy(buf, first, width * bpp);
}
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_Blt(
LPDIRECTDRAWSURFACE4 iface,LPRECT rdst,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,
DWORD dwFlags,LPDDBLTFX lpbltfx
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
RECT xdst,xsrc;
DDSURFACEDESC ddesc,sdesc;
HRESULT ret = DD_OK;
int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
int x, y;
LPBYTE dbuf, sbuf;
TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
if (src) IDirectDrawSurface4_Lock(src, NULL, &sdesc, 0, 0);
IDirectDrawSurface4_Lock(iface,NULL,&ddesc,0,0);
if (TRACE_ON(ddraw)) {
if (rdst) TRACE("\tdestrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
if (rsrc) TRACE("\tsrcrect :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
TRACE("\tflags: ");
_dump_DDBLT(dwFlags);
if (dwFlags & DDBLT_DDFX) {
TRACE("\tblitfx: ");
_dump_DDBLTFX(lpbltfx->dwDDFX);
}
}
if (rdst) {
if ((rdst->top < 0) ||
(rdst->left < 0) ||
(rdst->bottom < 0) ||
(rdst->right < 0)) {
ERR(" Negative values in LPRECT !!!\n");
goto release;
}
memcpy(&xdst,rdst,sizeof(xdst));
} else {
xdst.top = 0;
xdst.bottom = ddesc.dwHeight;
xdst.left = 0;
xdst.right = ddesc.dwWidth;
}
if (rsrc) {
if ((rsrc->top < 0) ||
(rsrc->left < 0) ||
(rsrc->bottom < 0) ||
(rsrc->right < 0)) {
ERR(" Negative values in LPRECT !!!\n");
goto release;
}
memcpy(&xsrc,rsrc,sizeof(xsrc));
} else {
if (src) {
xsrc.top = 0;
xsrc.bottom = sdesc.dwHeight;
xsrc.left = 0;
xsrc.right = sdesc.dwWidth;
} else {
memset(&xsrc,0,sizeof(xsrc));
}
}
if (src) assert((xsrc.bottom-xsrc.top) <= sdesc.dwHeight);
/* truncate dst rect to dest surface. */
if ((xdst.bottom-xdst.top) > ddesc.dwHeight)
xdst.bottom = xdst.top+ddesc.dwHeight;
if ((xdst.right-xdst.left) > ddesc.dwWidth)
xdst.right = xdst.left+ddesc.dwWidth;
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;
assert(width <= ddesc.lPitch);
dbuf = (BYTE*)ddesc.u1.lpSurface+(xdst.top*ddesc.lPitch)+(xdst.left*bpp);
dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
/* First, all the 'source-less' blits */
if (dwFlags & DDBLT_COLORFILL) {
ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
ddesc.lPitch, lpbltfx->u4.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:
ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.lPitch,0);
break;
case 0xAA0029: /* No-op */
break;
case WHITENESS:
ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.lPitch,~0);
break;
default:
FIXME("Unsupported raster op: %08lx Pattern: %p\n", lpbltfx->dwROP, lpbltfx->u4.lpDDSPattern);
goto error;
}
dwFlags &= ~DDBLT_ROP;
}
if (dwFlags & DDBLT_DDROPS) {
FIXME("\tDdraw Raster Ops: %08lx Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->u4.lpDDSPattern);
}
/* Now the 'with source' blits */
if (src) {
LPBYTE sbase;
int sx, xinc, sy, yinc;
if (!dstwidth || !dstheight) /* hmm... stupid program ? */
goto release;
sbase = (BYTE*)sdesc.u1.lpSurface+(xsrc.top*sdesc.lPitch)+xsrc.left*bpp;
xinc = (srcwidth << 16) / dstwidth;
yinc = (srcheight << 16) / dstheight;
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;
for (y = 0; y < dstheight; y++) {
memcpy(dbuf, sbuf, width);
sbuf += sdesc.lPitch;
dbuf += ddesc.lPitch;
}
} else {
/* Stretching in Y direction only */
for (y = sy = 0; y < dstheight; y++, sy += yinc) {
sbuf = sbase + (sy >> 16) * sdesc.lPitch;
memcpy(dbuf, sbuf, width);
dbuf += ddesc.lPitch;
}
}
} else {
/* Stretching in X direction */
int last_sy = -1;
for (y = sy = 0; y < dstheight; y++, sy += yinc) {
sbuf = sbase + (sy >> 16) * sdesc.lPitch;
if ((sy >> 16) == (last_sy >> 16)) {
/* this sourcerow is the same as last sourcerow -
* copy already stretched row
*/
memcpy(dbuf, dbuf - ddesc.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)
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]<<16)|(s[1]<<8)|s[2];
d[0] = (pixel>>16)&0xff;
d[1] = (pixel>> 8)&0xff;
d[2] = (pixel )&0xff;
d+=3;
}
break;
}
default:
FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
ret = DDERR_UNSUPPORTED;
goto error;
}
#undef STRETCH_ROW
}
dbuf += ddesc.lPitch;
last_sy = sy;
}
}
} else if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYDEST)) {
DWORD keylow, keyhigh;
if (dwFlags & DDBLT_KEYSRC) {
keylow = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
} else {
/* I'm not sure if this is correct */
FIXME("DDBLT_KEYDEST not fully supported yet.\n");
keylow = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
}
for (y = sy = 0; y < dstheight; y++, sy += yinc) {
sbuf = sbase + (sy >> 16) * sdesc.lPitch;
#define COPYROW_COLORKEY(type) { \
type *s = (type *) sbuf, *d = (type *) dbuf, tmp; \
for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
tmp = s[sx >> 16]; \
if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
} \
break; }
switch (bpp) {
case 1: COPYROW_COLORKEY(BYTE)
case 2: COPYROW_COLORKEY(WORD)
case 4: COPYROW_COLORKEY(DWORD)
default:
FIXME("%s color-keyed blit not implemented for bpp %d!\n",
(dwFlags & DDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
ret = DDERR_UNSUPPORTED;
goto error;
}
dbuf += ddesc.lPitch;
}
#undef COPYROW_COLORKEY
dwFlags &= ~(DDBLT_KEYSRC | DDBLT_KEYDEST);
}
}
error:
if (dwFlags && FIXME_ON(ddraw)) {
FIXME("\tUnsupported flags: ");
_dump_DDBLT(dwFlags);
}
release:
IDirectDrawSurface4_Unlock(iface,ddesc.u1.lpSurface);
if (src) IDirectDrawSurface4_Unlock(src,sdesc.u1.lpSurface);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_BltFast(
LPDIRECTDRAWSURFACE4 iface,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE4 src,
LPRECT rsrc,DWORD trans
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
int bpp, w, h, x, y;
DDSURFACEDESC ddesc,sdesc;
HRESULT ret = DD_OK;
LPBYTE sbuf, dbuf;
RECT rsrc2;
if (TRACE_ON(ddraw)) {
FIXME("(%p)->(%ld,%ld,%p,%p,%08lx)\n",
This,dstx,dsty,src,rsrc,trans
);
FIXME(" trans:");
if (FIXME_ON(ddraw))
_dump_DDBLTFAST(trans);
if (rsrc)
FIXME("\tsrcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
else
FIXME(" srcrect: NULL\n");
}
/* We need to lock the surfaces, or we won't get refreshes when done. */
IDirectDrawSurface4_Lock(src, NULL,&sdesc,DDLOCK_READONLY, 0);
IDirectDrawSurface4_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
if (!rsrc) {
WARN("rsrc is NULL!\n");
rsrc = &rsrc2;
rsrc->left = rsrc->top = 0;
rsrc->right = sdesc.dwWidth;
rsrc->bottom = sdesc.dwHeight;
}
bpp = GET_BPP(This->s.surface_desc);
sbuf = (BYTE *)sdesc.u1.lpSurface+(rsrc->top*sdesc.lPitch)+rsrc->left*bpp;
dbuf = (BYTE *)ddesc.u1.lpSurface+(dsty*ddesc.lPitch)+dstx* bpp;
h=rsrc->bottom-rsrc->top;
if (h>ddesc.dwHeight-dsty) h=ddesc.dwHeight-dsty;
if (h>sdesc.dwHeight-rsrc->top) h=sdesc.dwHeight-rsrc->top;
if (h<0) h=0;
w=rsrc->right-rsrc->left;
if (w>ddesc.dwWidth-dstx) w=ddesc.dwWidth-dstx;
if (w>sdesc.dwWidth-rsrc->left) w=sdesc.dwWidth-rsrc->left;
if (w<0) w=0;
if (trans & (DDBLTFAST_SRCCOLORKEY | DDBLTFAST_DESTCOLORKEY)) {
DWORD keylow, keyhigh;
if (trans & DDBLTFAST_SRCCOLORKEY) {
keylow = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
} else {
/* I'm not sure if this is correct */
FIXME("DDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
keylow = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
}
#define COPYBOX_COLORKEY(type) { \
type *d = (type *)dbuf, *s = (type *)sbuf, tmp; \
s = (type *) ((BYTE *) sdesc.u1.lpSurface + (rsrc->top * sdesc.lPitch) + rsrc->left * bpp); \
d = (type *) ((BYTE *) ddesc.u1.lpSurface + (dsty * ddesc.lPitch) + dstx * bpp); \
for (y = 0; y < h; y++) { \
for (x = 0; x < w; x++) { \
tmp = s[x]; \
if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
} \
(LPBYTE)s += sdesc.lPitch; \
(LPBYTE)d += ddesc.lPitch; \
} \
break; \
}
switch (bpp) {
case 1: COPYBOX_COLORKEY(BYTE)
case 2: COPYBOX_COLORKEY(WORD)
case 4: COPYBOX_COLORKEY(DWORD)
default:
FIXME("Source color key blitting not supported for bpp %d\n",bpp*8);
ret = DDERR_UNSUPPORTED;
goto error;
}
#undef COPYBOX_COLORKEY
} else {
int width = w * bpp;
for (y = 0; y < h; y++) {
memcpy(dbuf, sbuf, width);
sbuf += sdesc.lPitch;
dbuf += ddesc.lPitch;
}
}
error:
IDirectDrawSurface4_Unlock(iface,ddesc.u1.lpSurface);
IDirectDrawSurface4_Unlock(src,sdesc.u1.lpSurface);
return ret;
}
HRESULT WINAPI IDirectDrawSurface4Impl_BltBatch(
LPDIRECTDRAWSURFACE4 iface,LPDDBLTBATCH ddbltbatch,DWORD x,DWORD y
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->BltBatch(%p,%08lx,%08lx),stub!\n",This,ddbltbatch,x,y);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetCaps(
LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS caps
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->GetCaps(%p)\n",This,caps);
caps->dwCaps = DDSCAPS_PALETTE; /* probably more */
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetSurfaceDesc(
LPDIRECTDRAWSURFACE4 iface,LPDDSURFACEDESC ddsd
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->GetSurfaceDesc(%p)\n", This,ddsd);
/* Simply copy the surface description stored in the object */
*ddsd = This->s.surface_desc;
if (TRACE_ON(ddraw)) { _dump_surface_desc(ddsd); }
return DD_OK;
}
ULONG WINAPI IDirectDrawSurface4Impl_AddRef(LPDIRECTDRAWSURFACE4 iface) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->() incrementing from %lu.\n", This, This->ref );
return ++(This->ref);
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetAttachedSurface(
LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE4 *lpdsf
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
int i,found = 0,xstart;
struct _surface_chain *chain;
TRACE("(%p)->GetAttachedSurface(%p,%p)\n", This, lpddsd, lpdsf);
if (TRACE_ON(ddraw)) {
TRACE(" caps ");_dump_DDSCAPS((void *) &(lpddsd->dwCaps));
DPRINTF("\n");
}
chain = This->s.chain;
if (!chain)
return DDERR_NOTFOUND;
for (i=0;i<chain->nrofsurfaces;i++)
if (chain->surfaces[i] == This)
break;
xstart = i;
for (i=0;i<chain->nrofsurfaces;i++) {
if ((SDDSCAPS(chain->surfaces[(xstart+i)%chain->nrofsurfaces])&lpddsd->dwCaps) == lpddsd->dwCaps) {
#if 0
if (found) /* may not find the same caps twice, (doc) */
return DDERR_INVALIDPARAMS;/*FIXME: correct? */
#endif
found = (i+1)+xstart;
}
}
if (!found)
return DDERR_NOTFOUND;
*lpdsf = (LPDIRECTDRAWSURFACE4)chain->surfaces[found-1-xstart];
/* For EverQuest testing */
IDirectDrawSurface4_AddRef(*lpdsf);
TRACE("found %p\n",*lpdsf);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_Initialize(
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->(%p, %p)\n",This,ddraw,lpdsfd);
return DDERR_ALREADYINITIALIZED;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetPixelFormat(
LPDIRECTDRAWSURFACE4 iface,LPDDPIXELFORMAT pf
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->(%p)\n",This,pf);
*pf = This->s.surface_desc.ddpfPixelFormat;
if (TRACE_ON(ddraw)) { _dump_pixelformat(pf); DPRINTF("\n"); }
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetBltStatus(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(0x%08lx),stub!\n",This,dwFlags);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetOverlayPosition(
LPDIRECTDRAWSURFACE4 iface,LPLONG x1,LPLONG x2
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%p,%p),stub!\n",This,x1,x2);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_SetClipper(
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWCLIPPER lpClipper
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->(%p)!\n",This,lpClipper);
if (This->s.lpClipper) IDirectDrawClipper_Release( This->s.lpClipper );
This->s.lpClipper = lpClipper;
if (lpClipper) IDirectDrawClipper_AddRef( lpClipper );
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_AddAttachedSurface(
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 surf
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
IDirectDrawSurface4Impl*isurf = (IDirectDrawSurface4Impl*)surf;
int i;
struct _surface_chain *chain;
FIXME("(%p)->(%p)\n",This,surf);
chain = This->s.chain;
/* IDirectDrawSurface4_AddRef(surf); */
if (chain) {
for (i=0;i<chain->nrofsurfaces;i++)
if (chain->surfaces[i] == isurf)
FIXME("attaching already attached surface %p to %p!\n",iface,isurf);
} else {
chain = HeapAlloc(GetProcessHeap(),0,sizeof(*chain));
chain->nrofsurfaces = 1;
chain->surfaces = HeapAlloc(GetProcessHeap(),0,sizeof(chain->surfaces[0]));
chain->surfaces[0] = This;
This->s.chain = chain;
}
if (chain->surfaces)
chain->surfaces = HeapReAlloc(
GetProcessHeap(),
0,
chain->surfaces,
sizeof(chain->surfaces[0])*(chain->nrofsurfaces+1)
);
else
chain->surfaces = HeapAlloc(GetProcessHeap(),0,sizeof(chain->surfaces[0]));
isurf->s.chain = chain;
chain->surfaces[chain->nrofsurfaces++] = isurf;
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
DDSURFACEDESC desc;
BITMAPINFO *b_info;
UINT usage;
HDC ddc;
TRACE("(%p)->GetDC(%p)\n",This,lphdc);
/* Creates a DIB Section of the same size / format as the surface */
IDirectDrawSurface4_Lock(iface,NULL,&desc,0,0);
if (This->s.hdc == 0) {
switch (desc.ddpfPixelFormat.u.dwRGBBitCount) {
case 16:
case 32:
#if 0 /* This should be filled if Wine's DIBSection did understand BI_BITFIELDS */
b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
break;
#endif
case 24:
b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
break;
default:
b_info = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (2 << desc.ddpfPixelFormat.u.dwRGBBitCount));
break;
}
b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
b_info->bmiHeader.biWidth = desc.dwWidth;
b_info->bmiHeader.biHeight = -desc.dwHeight;
b_info->bmiHeader.biPlanes = 1;
b_info->bmiHeader.biBitCount = desc.ddpfPixelFormat.u.dwRGBBitCount;
#if 0
if ((desc.ddpfPixelFormat.u.dwRGBBitCount != 16) &&
(desc.ddpfPixelFormat.u.dwRGBBitCount != 32))
#endif
b_info->bmiHeader.biCompression = BI_RGB;
#if 0
else
b_info->bmiHeader.biCompression = BI_BITFIELDS;
#endif
b_info->bmiHeader.biSizeImage = (desc.ddpfPixelFormat.u.dwRGBBitCount / 8) * desc.dwWidth * desc.dwHeight;
b_info->bmiHeader.biXPelsPerMeter = 0;
b_info->bmiHeader.biYPelsPerMeter = 0;
b_info->bmiHeader.biClrUsed = 0;
b_info->bmiHeader.biClrImportant = 0;
switch (desc.ddpfPixelFormat.u.dwRGBBitCount) {
case 16:
case 32:
#if 0
{
DWORD *masks = (DWORD *) &(b_info->bmiColors);
usage = 0;
masks[0] = desc.ddpfPixelFormat.u1.dwRBitMask;
masks[1] = desc.ddpfPixelFormat.u2.dwGBitMask;
masks[2] = desc.ddpfPixelFormat.u3.dwBBitMask;
}
break;
#endif
case 24:
/* Nothing to do */
usage = DIB_RGB_COLORS;
break;
default: {
int i;
/* Fill the palette */
usage = DIB_RGB_COLORS;
if (This->s.palette == NULL) {
ERR("Bad palette !!!\n");
} else {
RGBQUAD *rgb = (RGBQUAD *) &(b_info->bmiColors);
PALETTEENTRY *pent = (PALETTEENTRY *)&(This->s.palette->palents);
for (i=0;i<(1<<desc.ddpfPixelFormat.u.dwRGBBitCount);i++) {
rgb[i].rgbBlue = pent[i].peBlue;
rgb[i].rgbRed = pent[i].peRed;
rgb[i].rgbGreen = pent[i].peGreen;
}
}
}
break;
}
ddc = CreateDCA("DISPLAY",NULL,NULL,NULL);
This->s.DIBsection = ddc ? DIB_CreateDIBSection(ddc,
b_info,
usage,
&(This->s.bitmap_data),
0,
(DWORD)desc.u1.lpSurface,
desc.lPitch
) : 0;
if (!This->s.DIBsection) {
ERR("CreateDIBSection failed!\n");
if (ddc) DeleteDC(ddc);
HeapFree(GetProcessHeap(), 0, b_info);
return E_FAIL;
}
TRACE("DIBSection at : %p\n", This->s.bitmap_data);
/* b_info is not useful anymore */
HeapFree(GetProcessHeap(), 0, b_info);
/* Create the DC */
This->s.hdc = CreateCompatibleDC(ddc);
This->s.holdbitmap = SelectObject(This->s.hdc, This->s.DIBsection);
if (ddc) DeleteDC(ddc);
}
if (This->s.bitmap_data != desc.u1.lpSurface) {
FIXME("DIBSection not created for frame buffer, reverting to old code\n");
/* Copy our surface in the DIB section */
if ((GET_BPP(desc) * desc.dwWidth) == desc.lPitch)
memcpy(This->s.bitmap_data,desc.u1.lpSurface,desc.lPitch*desc.dwHeight);
else
/* TODO */
FIXME("This case has to be done :/\n");
}
if (lphdc) {
TRACE("HDC : %08lx\n", (DWORD) This->s.hdc);
*lphdc = This->s.hdc;
}
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_ReleaseDC(LPDIRECTDRAWSURFACE4 iface,HDC hdc) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->(0x%08lx)\n",This,(long)hdc);
if (This->s.bitmap_data != This->s.surface_desc.u1.lpSurface) {
TRACE( "Copying DIBSection at : %p\n", This->s.bitmap_data);
/* Copy the DIB section to our surface */
if ((GET_BPP(This->s.surface_desc) * This->s.surface_desc.dwWidth) == This->s.surface_desc.lPitch) {
memcpy(This->s.surface_desc.u1.lpSurface, This->s.bitmap_data, This->s.surface_desc.lPitch * This->s.surface_desc.dwHeight);
} else {
/* TODO */
FIXME("This case has to be done :/\n");
}
}
/* Unlock the surface */
IDirectDrawSurface4_Unlock(iface,This->s.surface_desc.u1.lpSurface);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_QueryInterface(
LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
/* All DirectDrawSurface versions (1, 2, 3 and 4) use
* the same interface. And IUnknown does that too of course.
*/
if ( IsEqualGUID( &IID_IDirectDrawSurface4, refiid ) ||
IsEqualGUID( &IID_IDirectDrawSurface3, refiid ) ||
IsEqualGUID( &IID_IDirectDrawSurface2, refiid ) ||
IsEqualGUID( &IID_IDirectDrawSurface, refiid ) ||
IsEqualGUID( &IID_IUnknown, refiid )
) {
*obj = This;
IDirectDrawSurface4_AddRef(iface);
TRACE(" Creating IDirectDrawSurface interface (%p)\n", *obj);
return S_OK;
}
FIXME("(%p):interface for IID %s NOT found!\n",This,debugstr_guid(refiid));
return OLE_E_ENUM_NOMORE;
}
HRESULT WINAPI IDirectDrawSurface4Impl_IsLost(LPDIRECTDRAWSURFACE4 iface) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->(), stub!\n",This);
return DD_OK; /* hmm */
}
HRESULT WINAPI IDirectDrawSurface4Impl_EnumAttachedSurfaces(
LPDIRECTDRAWSURFACE4 iface,LPVOID context,LPDDENUMSURFACESCALLBACK esfcb
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
int i;
struct _surface_chain *chain = This->s.chain;
TRACE("(%p)->(%p,%p)\n",This,context,esfcb);
if (chain) {
for (i=0;i<chain->nrofsurfaces;i++) {
TRACE( "Enumerating attached surface (%p)\n", chain->surfaces[i]);
if (esfcb((LPDIRECTDRAWSURFACE) chain->surfaces[i], &(chain->surfaces[i]->s.surface_desc), context) == DDENUMRET_CANCEL)
return DD_OK; /* FIXME: return value correct? */
}
}
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_Restore(LPDIRECTDRAWSURFACE4 iface) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(),stub!\n",This);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_SetColorKey(
LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY ckey )
{
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->(0x%08lx,%p)\n",This,dwFlags,ckey);
if (TRACE_ON(ddraw)) {
_dump_colorkeyflag(dwFlags);
DPRINTF(" : ");
_dump_DDCOLORKEY((void *) ckey);
DPRINTF("\n");
}
/* If this surface was loaded as a texture, call also the texture
* SetColorKey callback. FIXME: hack approach :(
*/
if (This->s.texture)
This->s.SetColorKey_cb(This->s.texture, dwFlags, ckey);
if( dwFlags & DDCKEY_SRCBLT ) {
dwFlags &= ~DDCKEY_SRCBLT;
This->s.surface_desc.dwFlags |= DDSD_CKSRCBLT;
memcpy( &(This->s.surface_desc.ddckCKSrcBlt), ckey, sizeof( *ckey ) );
}
if( dwFlags & DDCKEY_DESTBLT ) {
dwFlags &= ~DDCKEY_DESTBLT;
This->s.surface_desc.dwFlags |= DDSD_CKDESTBLT;
memcpy( &(This->s.surface_desc.ddckCKDestBlt), ckey, sizeof( *ckey ) );
}
if( dwFlags & DDCKEY_SRCOVERLAY ) {
dwFlags &= ~DDCKEY_SRCOVERLAY;
This->s.surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
memcpy( &(This->s.surface_desc.ddckCKSrcOverlay), ckey, sizeof( *ckey ) );
}
if( dwFlags & DDCKEY_DESTOVERLAY ) {
dwFlags &= ~DDCKEY_DESTOVERLAY;
This->s.surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
memcpy( &(This->s.surface_desc.ddckCKDestOverlay), ckey, sizeof( *ckey ) );
}
if( dwFlags )
FIXME("unhandled dwFlags: 0x%08lx\n", dwFlags );
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_AddOverlayDirtyRect(
LPDIRECTDRAWSURFACE4 iface, LPRECT lpRect
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%p),stub!\n",This,lpRect);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_DeleteAttachedSurface(
LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags,
LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
int i;
struct _surface_chain *chain;
TRACE("(%p)->(0x%08lx,%p)\n",This,dwFlags,lpDDSAttachedSurface);
chain = This->s.chain;
for (i=0;i<chain->nrofsurfaces;i++) {
if ((IDirectDrawSurface4Impl*)lpDDSAttachedSurface==chain->surfaces[i]){
/* There is no AddRef in AddAttachedSurface, so why a release here :-)
IDirectDrawSurface4_Release(lpDDSAttachedSurface); */
chain->surfaces[i]->s.chain = NULL;
memcpy( chain->surfaces+i,
chain->surfaces+(i+1),
(chain->nrofsurfaces-i-1)*sizeof(chain->surfaces[i])
);
chain->surfaces = HeapReAlloc(
GetProcessHeap(),
0,
chain->surfaces,
sizeof(chain->surfaces[i])*(chain->nrofsurfaces-1)
);
chain->nrofsurfaces--;
return DD_OK;
}
}
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_EnumOverlayZOrders(
LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPVOID lpContext,
LPDDENUMSURFACESCALLBACK lpfnCallback
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(0x%08lx,%p,%p),stub!\n", This,dwFlags,
lpContext, lpfnCallback );
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetClipper(
LPDIRECTDRAWSURFACE4 iface, LPDIRECTDRAWCLIPPER* lplpDDClipper
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%p),stub!\n", This, lplpDDClipper);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetColorKey(
LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY lpDDColorKey
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->(0x%08lx,%p)\n", This, dwFlags, lpDDColorKey);
if( dwFlags & DDCKEY_SRCBLT ) {
dwFlags &= ~DDCKEY_SRCBLT;
memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKSrcBlt), sizeof( *lpDDColorKey ) );
}
if( dwFlags & DDCKEY_DESTBLT ) {
dwFlags &= ~DDCKEY_DESTBLT;
memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKDestBlt), sizeof( *lpDDColorKey ) );
}
if( dwFlags & DDCKEY_SRCOVERLAY ) {
dwFlags &= ~DDCKEY_SRCOVERLAY;
memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKSrcOverlay), sizeof( *lpDDColorKey ) );
}
if( dwFlags & DDCKEY_DESTOVERLAY ) {
dwFlags &= ~DDCKEY_DESTOVERLAY;
memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKDestOverlay), sizeof( *lpDDColorKey ) );
}
if( dwFlags )
FIXME("unhandled dwFlags: 0x%08lx\n", dwFlags );
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetFlipStatus(
LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetPalette(
LPDIRECTDRAWSURFACE4 iface, LPDIRECTDRAWPALETTE* lplpDDPalette
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
TRACE("(%p)->(%p),stub!\n", This, lplpDDPalette);
if (!This->s.palette)
return DDERR_NOPALETTEATTACHED;
IDirectDrawPalette_AddRef( (IDirectDrawPalette*) This->s.palette );
*lplpDDPalette = (IDirectDrawPalette*) This->s.palette;
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_SetOverlayPosition(
LPDIRECTDRAWSURFACE4 iface, LONG lX, LONG lY
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%ld,%ld),stub!\n", This, lX, lY);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlay(
LPDIRECTDRAWSURFACE4 iface, LPRECT lpSrcRect,
LPDIRECTDRAWSURFACE4 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags,
LPDDOVERLAYFX lpDDOverlayFx
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%p,%p,%p,0x%08lx,%p),stub!\n", This,
lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayDisplay(
LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayZOrder(
LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags,LPDIRECTDRAWSURFACE4 lpDDSReference
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(0x%08lx,%p),stub!\n", This, dwFlags, lpDDSReference);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetDDInterface(
LPDIRECTDRAWSURFACE4 iface, LPVOID* lplpDD
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%p),stub!\n", This, lplpDD);
/* Not sure about that... */
IDirectDraw_AddRef((LPDIRECTDRAW)This->s.ddraw),
*lplpDD = (void *) This->s.ddraw;
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_PageLock(
LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_PageUnlock(
LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_SetSurfaceDesc(
LPDIRECTDRAWSURFACE4 iface, LPDDSURFACEDESC lpDDSD, DWORD dwFlags
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%p,0x%08lx),stub!\n", This, lpDDSD, dwFlags);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_SetPrivateData(
LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag, LPVOID lpData, DWORD cbSize,
DWORD dwFlags
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%p,%p,%ld,%08lx\n", This, guidTag, lpData, cbSize, dwFlags);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetPrivateData(
LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag, LPVOID lpBuffer,
LPDWORD lpcbBufferSize
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%p,%p,%p)\n", This, guidTag, lpBuffer, lpcbBufferSize);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_FreePrivateData(
LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%p)\n", This, guidTag);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_GetUniquenessValue(
LPDIRECTDRAWSURFACE4 iface, LPDWORD lpValue
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)->(%p)\n", This, lpValue);
return DD_OK;
}
HRESULT WINAPI IDirectDrawSurface4Impl_ChangeUniquenessValue(
LPDIRECTDRAWSURFACE4 iface
) {
ICOM_THIS(IDirectDrawSurface4Impl,iface);
FIXME("(%p)\n", This);
return DD_OK;
}