/* DirectDrawSurface base implementation * * Copyright 1997-2000 Marcus Meissner * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff) */ #include "config.h" #include "winerror.h" #include #include #include #include #include #include #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;inrofsurfaces;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;inrofsurfaces;i++) if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FRONTBUFFER) break; if (i==chain->nrofsurfaces) { /* we do not have a frontbuffer either */ for (i=0;inrofsurfaces;i++) if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FLIP) { SDDSCAPS(chain->surfaces[i])|=DDSCAPS_FRONTBUFFER; break; } for (j=i+1;jnrofsurfaces+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); assert((xdst.bottom-xdst.top) <= ddesc.dwHeight); 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; 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;inrofsurfaces;i++) if (chain->surfaces[i] == This) break; xstart = i; for (i=0;inrofsurfaces;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;inrofsurfaces;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<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;inrofsurfaces;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;inrofsurfaces;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; }