2 * IWineD3DSurface Implementation of management(non-rendering) functions
4 * Copyright 1998 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
6 * Copyright 2002-2005 Jason Edmeades
7 * Copyright 2002-2003 Raphael Junqueira
8 * Copyright 2004 Christian Costa
9 * Copyright 2005 Oliver Stieber
10 * Copyright 2006-2007 Stefan Dösinger for CodeWeavers
11 * Copyright 2007 Henri Verbeet
12 * Copyright 2006-2007 Roderick Colenbrander
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/port.h"
31 #include "wined3d_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
35 /* Do NOT define GLINFO_LOCATION in this file. THIS CODE MUST NOT USE IT */
37 /* *******************************************
38 IWineD3DSurface IUnknown parts follow
39 ******************************************* */
40 HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
42 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
43 /* Warn ,but be nice about things */
44 TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
46 if (IsEqualGUID(riid, &IID_IUnknown)
47 || IsEqualGUID(riid, &IID_IWineD3DBase)
48 || IsEqualGUID(riid, &IID_IWineD3DResource)
49 || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
50 IUnknown_AddRef((IUnknown*)iface);
58 ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface) {
59 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
60 ULONG ref = InterlockedIncrement(&This->resource.ref);
61 TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1);
65 /* ****************************************************
66 IWineD3DSurface IWineD3DResource parts follow
67 **************************************************** */
68 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
69 return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
72 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
73 return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
76 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
77 return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
80 HRESULT WINAPI IWineD3DBaseSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
81 return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
84 DWORD WINAPI IWineD3DBaseSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
85 return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
88 DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
89 return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
92 WINED3DRESOURCETYPE WINAPI IWineD3DBaseSurfaceImpl_GetType(IWineD3DSurface *iface) {
93 TRACE("(%p) : calling resourceimpl_GetType\n", iface);
94 return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
97 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
98 TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
99 return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
102 /* ******************************************************
103 IWineD3DSurface IWineD3DSurface parts follow
104 ****************************************************** */
106 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
107 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
108 IWineD3DBase *container = 0;
110 TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
113 ERR("Called without a valid ppContainer.\n");
117 * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
118 * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
119 * GetContainer will return the Direct3D device used to create the surface.
121 if (This->container) {
122 container = This->container;
124 container = (IWineD3DBase *)This->resource.wineD3DDevice;
127 TRACE("Relaying to QueryInterface\n");
128 return IUnknown_QueryInterface(container, riid, ppContainer);
131 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
132 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
134 TRACE("(%p) : copying into %p\n", This, pDesc);
135 if(pDesc->Format != NULL) *(pDesc->Format) = This->resource.format;
136 if(pDesc->Type != NULL) *(pDesc->Type) = This->resource.resourceType;
137 if(pDesc->Usage != NULL) *(pDesc->Usage) = This->resource.usage;
138 if(pDesc->Pool != NULL) *(pDesc->Pool) = This->resource.pool;
139 if(pDesc->Size != NULL) *(pDesc->Size) = This->resource.size; /* dx8 only */
140 if(pDesc->MultiSampleType != NULL) *(pDesc->MultiSampleType) = This->currentDesc.MultiSampleType;
141 if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
142 if(pDesc->Width != NULL) *(pDesc->Width) = This->currentDesc.Width;
143 if(pDesc->Height != NULL) *(pDesc->Height) = This->currentDesc.Height;
147 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
148 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
149 TRACE("(%p)->(%x)\n", This, Flags);
153 case WINEDDGBS_CANBLT:
154 case WINEDDGBS_ISBLTDONE:
158 return WINED3DERR_INVALIDCALL;
162 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
163 /* XXX: DDERR_INVALIDSURFACETYPE */
165 TRACE("(%p)->(%08x)\n",iface,Flags);
167 case WINEDDGFS_CANFLIP:
168 case WINEDDGFS_ISFLIPDONE:
172 return WINED3DERR_INVALIDCALL;
176 HRESULT WINAPI IWineD3DBaseSurfaceImpl_IsLost(IWineD3DSurface *iface) {
177 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
178 TRACE("(%p)\n", This);
180 /* D3D8 and 9 loose full devices, ddraw only surfaces */
181 return This->Flags & SFLAG_LOST ? WINED3DERR_DEVICELOST : WINED3D_OK;
184 HRESULT WINAPI IWineD3DBaseSurfaceImpl_Restore(IWineD3DSurface *iface) {
185 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
186 TRACE("(%p)\n", This);
188 /* So far we don't lose anything :) */
189 This->Flags &= ~SFLAG_LOST;
193 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
194 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
195 IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
196 TRACE("(%p)->(%p)\n", This, Pal);
198 if(This->palette != NULL)
199 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
200 This->palette->Flags &= ~WINEDDPCAPS_PRIMARYSURFACE;
202 if(PalImpl != NULL) {
203 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
204 /* Set the device's main palette if the palette
205 * wasn't a primary palette before
207 if(!(PalImpl->Flags & WINEDDPCAPS_PRIMARYSURFACE)) {
208 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
211 for(i=0; i < 256; i++) {
212 device->palettes[device->currentPalette][i] = PalImpl->palents[i];
216 (PalImpl)->Flags |= WINEDDPCAPS_PRIMARYSURFACE;
219 This->palette = PalImpl;
221 return IWineD3DSurface_RealizePalette(iface);
224 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, WINEDDCOLORKEY *CKey) {
225 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
226 TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
228 if ((Flags & WINEDDCKEY_COLORSPACE) != 0) {
229 FIXME(" colorkey value not supported (%08x) !\n", Flags);
230 return WINED3DERR_INVALIDCALL;
233 /* Dirtify the surface, but only if a key was changed */
235 switch (Flags & ~WINEDDCKEY_COLORSPACE) {
236 case WINEDDCKEY_DESTBLT:
237 This->DestBltCKey = *CKey;
238 This->CKeyFlags |= WINEDDSD_CKDESTBLT;
241 case WINEDDCKEY_DESTOVERLAY:
242 This->DestOverlayCKey = *CKey;
243 This->CKeyFlags |= WINEDDSD_CKDESTOVERLAY;
246 case WINEDDCKEY_SRCOVERLAY:
247 This->SrcOverlayCKey = *CKey;
248 This->CKeyFlags |= WINEDDSD_CKSRCOVERLAY;
251 case WINEDDCKEY_SRCBLT:
252 This->SrcBltCKey = *CKey;
253 This->CKeyFlags |= WINEDDSD_CKSRCBLT;
258 switch (Flags & ~WINEDDCKEY_COLORSPACE) {
259 case WINEDDCKEY_DESTBLT:
260 This->CKeyFlags &= ~WINEDDSD_CKDESTBLT;
263 case WINEDDCKEY_DESTOVERLAY:
264 This->CKeyFlags &= ~WINEDDSD_CKDESTOVERLAY;
267 case WINEDDCKEY_SRCOVERLAY:
268 This->CKeyFlags &= ~WINEDDSD_CKSRCOVERLAY;
271 case WINEDDCKEY_SRCBLT:
272 This->CKeyFlags &= ~WINEDDSD_CKSRCBLT;
280 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
281 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
282 TRACE("(%p)->(%p)\n", This, Pal);
284 *Pal = (IWineD3DPalette *) This->palette;
288 HRESULT WINAPI IWineD3DBaseSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
289 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
291 IWineD3DPaletteImpl *pal = This->palette;
293 TRACE("(%p)\n", This);
295 if(This->resource.format == WINED3DFMT_P8 ||
296 This->resource.format == WINED3DFMT_A8P8)
298 if(!This->Flags & SFLAG_INSYSMEM) {
299 FIXME("Palette changed with surface that does not have an up to date system memory copy\n");
301 TRACE("Dirtifying surface\n");
302 This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
305 if(This->Flags & SFLAG_DIBSECTION) {
306 TRACE("(%p): Updating the hdc's palette\n", This);
307 for (n=0; n<256; n++) {
309 col[n].rgbRed = pal->palents[n].peRed;
310 col[n].rgbGreen = pal->palents[n].peGreen;
311 col[n].rgbBlue = pal->palents[n].peBlue;
313 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
314 /* Use the default device palette */
315 col[n].rgbRed = device->palettes[device->currentPalette][n].peRed;
316 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
317 col[n].rgbBlue = device->palettes[device->currentPalette][n].peBlue;
319 col[n].rgbReserved = 0;
321 SetDIBColorTable(This->hDC, 0, 256, col);
327 DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
328 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
330 TRACE("(%p)\n", This);
332 /* DXTn formats don't have exact pitches as they are to the new row of blocks,
333 where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
334 ie pitch = (width/4) * bytes per block */
335 if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
336 ret = ((This->currentDesc.Width + 3) >> 2) << 3;
337 else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
338 This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
339 ret = ((This->currentDesc.Width + 3) >> 2) << 4;
341 unsigned char alignment = This->resource.wineD3DDevice->surface_alignment;
342 ret = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
343 ret = (ret + alignment - 1) & ~(alignment - 1);
345 TRACE("(%p) Returning %d\n", This, ret);
349 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) {
350 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
352 FIXME("(%p)->(%d,%d) Stub!\n", This, X, Y);
354 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
356 TRACE("(%p): Not an overlay surface\n", This);
357 return WINEDDERR_NOTAOVERLAYSURFACE;
363 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) {
364 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
366 FIXME("(%p)->(%p,%p) Stub!\n", This, X, Y);
368 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
370 TRACE("(%p): Not an overlay surface\n", This);
371 return WINEDDERR_NOTAOVERLAYSURFACE;
377 HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) {
378 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
379 IWineD3DSurfaceImpl *RefImpl = (IWineD3DSurfaceImpl *) Ref;
381 FIXME("(%p)->(%08x,%p) Stub!\n", This, Flags, RefImpl);
383 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
385 TRACE("(%p): Not an overlay surface\n", This);
386 return WINEDDERR_NOTAOVERLAYSURFACE;
392 HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *SrcRect, IWineD3DSurface *DstSurface, RECT *DstRect, DWORD Flags, WINEDDOVERLAYFX *FX) {
393 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
394 IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface;
395 FIXME("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
397 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
399 TRACE("(%p): Not an overlay surface\n", This);
400 return WINEDDERR_NOTAOVERLAYSURFACE;
406 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface *iface, IWineD3DClipper *clipper)
408 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
409 TRACE("(%p)->(%p)\n", This, clipper);
411 This->clipper = clipper;
415 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetClipper(IWineD3DSurface *iface, IWineD3DClipper **clipper)
417 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
418 TRACE("(%p)->(%p)\n", This, clipper);
420 *clipper = This->clipper;
422 IWineD3DClipper_AddRef(*clipper);
427 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
428 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
430 TRACE("This %p, container %p\n", This, container);
432 /* We can't keep a reference to the container, since the container already keeps a reference to us. */
434 TRACE("Setting container to %p from %p\n", container, This->container);
435 This->container = container;