wined3d: Base surface move, part 2.
[wine] / dlls / wined3d / surface_base.c
1 /*
2  * IWineD3DSurface Implementation of management(non-rendering) functions
3  *
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
13  *
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.
18  *
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.
23  *
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
27  */
28
29 #include "config.h"
30 #include "wine/port.h"
31 #include "wined3d_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
34
35 /* Do NOT define GLINFO_LOCATION in this file. THIS CODE MUST NOT USE IT */
36
37 /* *******************************************
38    IWineD3DSurface IUnknown parts follow
39    ******************************************* */
40 HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
41 {
42     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
43     /* Warn ,but be nice about things */
44     TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
45
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);
51         *ppobj = This;
52         return S_OK;
53         }
54         *ppobj = NULL;
55         return E_NOINTERFACE;
56 }
57
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);
62     return ref;
63 }
64
65 /* ****************************************************
66    IWineD3DSurface IWineD3DResource parts follow
67    **************************************************** */
68 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
69     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
70 }
71
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);
74 }
75
76 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
77     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
78 }
79
80 HRESULT WINAPI IWineD3DBaseSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
81     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
82 }
83
84 DWORD   WINAPI IWineD3DBaseSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
85     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
86 }
87
88 DWORD   WINAPI IWineD3DBaseSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
89     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
90 }
91
92 WINED3DRESOURCETYPE WINAPI IWineD3DBaseSurfaceImpl_GetType(IWineD3DSurface *iface) {
93     TRACE("(%p) : calling resourceimpl_GetType\n", iface);
94     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
95 }
96
97 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
98     TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
99     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
100 }
101
102 /* ******************************************************
103    IWineD3DSurface IWineD3DSurface parts follow
104    ****************************************************** */
105
106 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
107     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
108     IWineD3DBase *container = 0;
109
110     TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
111
112     if (!ppContainer) {
113         ERR("Called without a valid ppContainer.\n");
114     }
115
116     /** From MSDN:
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.
120      */
121     if (This->container) {
122         container = This->container;
123     } else {
124         container = (IWineD3DBase *)This->resource.wineD3DDevice;
125     }
126
127     TRACE("Relaying to QueryInterface\n");
128     return IUnknown_QueryInterface(container, riid, ppContainer);
129 }
130
131 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
132     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
133
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;
144     return WINED3D_OK;
145 }
146
147 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
148     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
149     TRACE("(%p)->(%x)\n", This, Flags);
150
151     switch (Flags)
152     {
153         case WINEDDGBS_CANBLT:
154         case WINEDDGBS_ISBLTDONE:
155             return WINED3D_OK;
156
157         default:
158             return WINED3DERR_INVALIDCALL;
159     }
160 }
161
162 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
163     /* XXX: DDERR_INVALIDSURFACETYPE */
164
165     TRACE("(%p)->(%08x)\n",iface,Flags);
166     switch (Flags) {
167         case WINEDDGFS_CANFLIP:
168         case WINEDDGFS_ISFLIPDONE:
169             return WINED3D_OK;
170
171         default:
172             return WINED3DERR_INVALIDCALL;
173     }
174 }
175
176 HRESULT WINAPI IWineD3DBaseSurfaceImpl_IsLost(IWineD3DSurface *iface) {
177     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
178     TRACE("(%p)\n", This);
179
180     /* D3D8 and 9 loose full devices, ddraw only surfaces */
181     return This->Flags & SFLAG_LOST ? WINED3DERR_DEVICELOST : WINED3D_OK;
182 }
183
184 HRESULT WINAPI IWineD3DBaseSurfaceImpl_Restore(IWineD3DSurface *iface) {
185     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
186     TRACE("(%p)\n", This);
187
188     /* So far we don't lose anything :) */
189     This->Flags &= ~SFLAG_LOST;
190     return WINED3D_OK;
191 }
192
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);
197
198     if(This->palette != NULL)
199         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
200             This->palette->Flags &= ~WINEDDPCAPS_PRIMARYSURFACE;
201
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
206             */
207             if(!(PalImpl->Flags & WINEDDPCAPS_PRIMARYSURFACE)) {
208                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
209                 unsigned int i;
210
211                 for(i=0; i < 256; i++) {
212                     device->palettes[device->currentPalette][i] = PalImpl->palents[i];
213                 }
214             }
215
216             (PalImpl)->Flags |= WINEDDPCAPS_PRIMARYSURFACE;
217         }
218     }
219     This->palette = PalImpl;
220
221     return IWineD3DSurface_RealizePalette(iface);
222 }
223
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);
227
228     if ((Flags & WINEDDCKEY_COLORSPACE) != 0) {
229         FIXME(" colorkey value not supported (%08x) !\n", Flags);
230         return WINED3DERR_INVALIDCALL;
231     }
232
233     /* Dirtify the surface, but only if a key was changed */
234     if(CKey) {
235         switch (Flags & ~WINEDDCKEY_COLORSPACE) {
236             case WINEDDCKEY_DESTBLT:
237                 This->DestBltCKey = *CKey;
238                 This->CKeyFlags |= WINEDDSD_CKDESTBLT;
239                 break;
240
241             case WINEDDCKEY_DESTOVERLAY:
242                 This->DestOverlayCKey = *CKey;
243                 This->CKeyFlags |= WINEDDSD_CKDESTOVERLAY;
244                 break;
245
246             case WINEDDCKEY_SRCOVERLAY:
247                 This->SrcOverlayCKey = *CKey;
248                 This->CKeyFlags |= WINEDDSD_CKSRCOVERLAY;
249                 break;
250
251             case WINEDDCKEY_SRCBLT:
252                 This->SrcBltCKey = *CKey;
253                 This->CKeyFlags |= WINEDDSD_CKSRCBLT;
254                 break;
255         }
256     }
257     else {
258         switch (Flags & ~WINEDDCKEY_COLORSPACE) {
259             case WINEDDCKEY_DESTBLT:
260                 This->CKeyFlags &= ~WINEDDSD_CKDESTBLT;
261                 break;
262
263             case WINEDDCKEY_DESTOVERLAY:
264                 This->CKeyFlags &= ~WINEDDSD_CKDESTOVERLAY;
265                 break;
266
267             case WINEDDCKEY_SRCOVERLAY:
268                 This->CKeyFlags &= ~WINEDDSD_CKSRCOVERLAY;
269                 break;
270
271             case WINEDDCKEY_SRCBLT:
272                 This->CKeyFlags &= ~WINEDDSD_CKSRCBLT;
273                 break;
274         }
275     }
276
277     return WINED3D_OK;
278 }
279
280 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
281     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
282     TRACE("(%p)->(%p)\n", This, Pal);
283
284     *Pal = (IWineD3DPalette *) This->palette;
285     return WINED3D_OK;
286 }
287
288 HRESULT WINAPI IWineD3DBaseSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
289     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
290     RGBQUAD col[256];
291     IWineD3DPaletteImpl *pal = This->palette;
292     unsigned int n;
293     TRACE("(%p)\n", This);
294
295     if(This->resource.format == WINED3DFMT_P8 ||
296        This->resource.format == WINED3DFMT_A8P8)
297     {
298         if(!This->Flags & SFLAG_INSYSMEM) {
299             FIXME("Palette changed with surface that does not have an up to date system memory copy\n");
300         }
301         TRACE("Dirtifying surface\n");
302         This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
303     }
304
305     if(This->Flags & SFLAG_DIBSECTION) {
306         TRACE("(%p): Updating the hdc's palette\n", This);
307         for (n=0; n<256; n++) {
308             if(pal) {
309                 col[n].rgbRed   = pal->palents[n].peRed;
310                 col[n].rgbGreen = pal->palents[n].peGreen;
311                 col[n].rgbBlue  = pal->palents[n].peBlue;
312             } else {
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;
318             }
319             col[n].rgbReserved = 0;
320         }
321         SetDIBColorTable(This->hDC, 0, 256, col);
322     }
323
324     return WINED3D_OK;
325 }
326
327 DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
328     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
329     DWORD ret;
330     TRACE("(%p)\n", This);
331
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;
340     else {
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);
344     }
345     TRACE("(%p) Returning %d\n", This, ret);
346     return ret;
347 }
348
349 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) {
350     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
351
352     FIXME("(%p)->(%d,%d) Stub!\n", This, X, Y);
353
354     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
355     {
356         TRACE("(%p): Not an overlay surface\n", This);
357         return WINEDDERR_NOTAOVERLAYSURFACE;
358     }
359
360     return WINED3D_OK;
361 }
362
363 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) {
364     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
365
366     FIXME("(%p)->(%p,%p) Stub!\n", This, X, Y);
367
368     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
369     {
370         TRACE("(%p): Not an overlay surface\n", This);
371         return WINEDDERR_NOTAOVERLAYSURFACE;
372     }
373
374     return WINED3D_OK;
375 }
376
377 HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) {
378     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
379     IWineD3DSurfaceImpl *RefImpl = (IWineD3DSurfaceImpl *) Ref;
380
381     FIXME("(%p)->(%08x,%p) Stub!\n", This, Flags, RefImpl);
382
383     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
384     {
385         TRACE("(%p): Not an overlay surface\n", This);
386         return WINEDDERR_NOTAOVERLAYSURFACE;
387     }
388
389     return WINED3D_OK;
390 }
391
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);
396
397     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
398     {
399         TRACE("(%p): Not an overlay surface\n", This);
400         return WINEDDERR_NOTAOVERLAYSURFACE;
401     }
402
403     return WINED3D_OK;
404 }
405
406 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface *iface, IWineD3DClipper *clipper)
407 {
408     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
409     TRACE("(%p)->(%p)\n", This, clipper);
410
411     This->clipper = clipper;
412     return WINED3D_OK;
413 }
414
415 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetClipper(IWineD3DSurface *iface, IWineD3DClipper **clipper)
416 {
417     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
418     TRACE("(%p)->(%p)\n", This, clipper);
419
420     *clipper = This->clipper;
421     if(*clipper) {
422         IWineD3DClipper_AddRef(*clipper);
423     }
424     return WINED3D_OK;
425 }
426
427 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
428     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
429
430     TRACE("This %p, container %p\n", This, container);
431
432     /* We can't keep a reference to the container, since the container already keeps a reference to us. */
433
434     TRACE("Setting container to %p from %p\n", container, This->container);
435     This->container = container;
436
437     return WINED3D_OK;
438 }