d3d9: Add tests for D3DSBT_PIXELSTATE stateblocks.
[wine] / dlls / d3d9 / texture.c
1 /*
2  * IDirect3DTexture9 implementation
3  *
4  * Copyright 2002-2005 Jason Edmeades
5  * Copyright 2002-2005 Raphael Junqueira
6  * Copyright 2005 Oliver Stieber
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "d3d9_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
27
28 /* IDirect3DTexture9 IUnknown parts follow: */
29 static HRESULT WINAPI IDirect3DTexture9Impl_QueryInterface(LPDIRECT3DTEXTURE9 iface, REFIID riid, LPVOID* ppobj) {
30     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
31
32     if (IsEqualGUID(riid, &IID_IUnknown)
33         || IsEqualGUID(riid, &IID_IDirect3DResource9)
34         || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9)
35         || IsEqualGUID(riid, &IID_IDirect3DTexture9)) {
36         IDirect3DTexture9_AddRef(iface);
37         *ppobj = This;
38         return S_OK;
39     }
40
41     WARN("(%p)->(%s,%p) not found\n", This, debugstr_guid(riid), ppobj);
42     *ppobj = NULL;
43     return E_NOINTERFACE;
44 }
45
46 static ULONG WINAPI IDirect3DTexture9Impl_AddRef(LPDIRECT3DTEXTURE9 iface) {
47     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
48     ULONG ref = InterlockedIncrement(&This->ref);
49
50     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
51
52     if (ref == 1)
53     {
54         IDirect3DDevice9Ex_AddRef(This->parentDevice);
55         wined3d_mutex_lock();
56         IWineD3DTexture_AddRef(This->wineD3DTexture);
57         wined3d_mutex_unlock();
58     }
59
60     return ref;
61 }
62
63 static ULONG WINAPI IDirect3DTexture9Impl_Release(LPDIRECT3DTEXTURE9 iface) {
64     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
65     ULONG ref = InterlockedDecrement(&This->ref);
66
67     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
68
69     if (ref == 0) {
70         IDirect3DDevice9Ex *parentDevice = This->parentDevice;
71
72         wined3d_mutex_lock();
73         IWineD3DTexture_Release(This->wineD3DTexture);
74         wined3d_mutex_unlock();
75
76         /* Release the device last, as it may cause the device to be destroyed. */
77         IDirect3DDevice9Ex_Release(parentDevice);
78     }
79     return ref;
80 }
81
82 /* IDirect3DTexture9 IDirect3DResource9 Interface follow: */
83 static HRESULT WINAPI IDirect3DTexture9Impl_GetDevice(LPDIRECT3DTEXTURE9 iface, IDirect3DDevice9** ppDevice) {
84     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
85     IWineD3DDevice *wined3d_device;
86     HRESULT hr;
87     TRACE("(%p) Relay\n", This);
88
89     wined3d_mutex_lock();
90     hr = IWineD3DTexture_GetDevice(This->wineD3DTexture, &wined3d_device);
91     if (SUCCEEDED(hr))
92     {
93         IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice);
94         IWineD3DDevice_Release(wined3d_device);
95     }
96     wined3d_mutex_unlock();
97
98     return hr;
99 }
100
101 static HRESULT WINAPI IDirect3DTexture9Impl_SetPrivateData(LPDIRECT3DTEXTURE9 iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
102     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
103     HRESULT hr;
104     TRACE("(%p) Relay\n", This);
105
106     wined3d_mutex_lock();
107     hr = IWineD3DTexture_SetPrivateData(This->wineD3DTexture, refguid, pData, SizeOfData, Flags);
108     wined3d_mutex_unlock();
109
110     return hr;
111 }
112
113 static HRESULT WINAPI IDirect3DTexture9Impl_GetPrivateData(LPDIRECT3DTEXTURE9 iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
114     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
115     HRESULT hr;
116     TRACE("(%p) Relay\n", This);
117
118     wined3d_mutex_lock();
119     hr = IWineD3DTexture_GetPrivateData(This->wineD3DTexture, refguid, pData, pSizeOfData);
120     wined3d_mutex_unlock();
121
122     return hr;
123 }
124
125 static HRESULT WINAPI IDirect3DTexture9Impl_FreePrivateData(LPDIRECT3DTEXTURE9 iface, REFGUID refguid) {
126     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
127     HRESULT hr;
128     TRACE("(%p) Relay\n", This);
129
130     wined3d_mutex_lock();
131     hr = IWineD3DTexture_FreePrivateData(This->wineD3DTexture, refguid);
132     wined3d_mutex_unlock();
133
134     return hr;
135 }
136
137 static DWORD WINAPI IDirect3DTexture9Impl_SetPriority(LPDIRECT3DTEXTURE9 iface, DWORD PriorityNew) {
138     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
139     DWORD ret;
140     TRACE("(%p) Relay\n", This);
141
142     wined3d_mutex_lock();
143     ret = IWineD3DTexture_SetPriority(This->wineD3DTexture, PriorityNew);
144     wined3d_mutex_unlock();
145
146     return ret;
147 }
148
149 static DWORD WINAPI IDirect3DTexture9Impl_GetPriority(LPDIRECT3DTEXTURE9 iface) {
150     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
151     DWORD ret;
152     TRACE("(%p) Relay\n", This);
153
154     wined3d_mutex_lock();
155     ret = IWineD3DTexture_GetPriority(This->wineD3DTexture);
156     wined3d_mutex_unlock();
157
158     return ret;
159 }
160
161 static void WINAPI IDirect3DTexture9Impl_PreLoad(LPDIRECT3DTEXTURE9 iface) {
162     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
163     TRACE("(%p) Relay\n", This);
164
165     wined3d_mutex_lock();
166     IWineD3DTexture_PreLoad(This->wineD3DTexture);
167     wined3d_mutex_unlock();
168 }
169
170 static D3DRESOURCETYPE WINAPI IDirect3DTexture9Impl_GetType(LPDIRECT3DTEXTURE9 iface) {
171     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
172     HRESULT ret;
173     TRACE("(%p) Relay\n", This);
174
175     wined3d_mutex_lock();
176     ret = IWineD3DTexture_GetType(This->wineD3DTexture);
177     wined3d_mutex_unlock();
178
179     return ret;
180 }
181
182 /* IDirect3DTexture9 IDirect3DBaseTexture9 Interface follow: */
183 static DWORD WINAPI IDirect3DTexture9Impl_SetLOD(LPDIRECT3DTEXTURE9 iface, DWORD LODNew) {
184     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
185     DWORD ret;
186     TRACE("(%p) Relay\n", This);
187
188     wined3d_mutex_lock();
189     ret = IWineD3DTexture_SetLOD(This->wineD3DTexture, LODNew);
190     wined3d_mutex_unlock();
191
192     return ret;
193 }
194
195 static DWORD WINAPI IDirect3DTexture9Impl_GetLOD(LPDIRECT3DTEXTURE9 iface) {
196     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
197     DWORD ret;
198     TRACE("(%p) Relay\n", This);
199
200     wined3d_mutex_lock();
201     ret = IWineD3DTexture_GetLOD(This->wineD3DTexture);
202     wined3d_mutex_unlock();
203
204     return ret;
205 }
206
207 static DWORD WINAPI IDirect3DTexture9Impl_GetLevelCount(LPDIRECT3DTEXTURE9 iface) {
208     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
209     DWORD ret;
210     TRACE("(%p) Relay\n", This);
211
212     wined3d_mutex_lock();
213     ret = IWineD3DTexture_GetLevelCount(This->wineD3DTexture);
214     wined3d_mutex_unlock();
215
216     return ret;
217 }
218
219 static HRESULT WINAPI IDirect3DTexture9Impl_SetAutoGenFilterType(LPDIRECT3DTEXTURE9 iface, D3DTEXTUREFILTERTYPE FilterType) {
220     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
221     HRESULT hr;
222     TRACE("(%p) Relay\n", This);
223
224     wined3d_mutex_lock();
225     hr = IWineD3DTexture_SetAutoGenFilterType(This->wineD3DTexture, (WINED3DTEXTUREFILTERTYPE) FilterType);
226     wined3d_mutex_unlock();
227
228     return hr;
229 }
230
231 static D3DTEXTUREFILTERTYPE WINAPI IDirect3DTexture9Impl_GetAutoGenFilterType(LPDIRECT3DTEXTURE9 iface) {
232     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
233     D3DTEXTUREFILTERTYPE ret;
234     TRACE("(%p) Relay\n", This);
235
236     wined3d_mutex_lock();
237     ret = (D3DTEXTUREFILTERTYPE) IWineD3DTexture_GetAutoGenFilterType(This->wineD3DTexture);
238     wined3d_mutex_unlock();
239
240     return ret;
241 }
242
243 static void WINAPI IDirect3DTexture9Impl_GenerateMipSubLevels(LPDIRECT3DTEXTURE9 iface) {
244     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
245     TRACE("(%p) Relay\n", This);
246
247     wined3d_mutex_lock();
248     IWineD3DTexture_GenerateMipSubLevels(This->wineD3DTexture);
249     wined3d_mutex_unlock();
250 }
251
252 /* IDirect3DTexture9 Interface follow: */
253 static HRESULT WINAPI IDirect3DTexture9Impl_GetLevelDesc(LPDIRECT3DTEXTURE9 iface, UINT Level, D3DSURFACE_DESC* pDesc) {
254     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
255     WINED3DSURFACE_DESC wined3ddesc;
256     HRESULT hr;
257
258     TRACE("(%p) Relay\n", This);
259
260     wined3d_mutex_lock();
261     hr = IWineD3DTexture_GetLevelDesc(This->wineD3DTexture, Level, &wined3ddesc);
262     wined3d_mutex_unlock();
263
264     if (SUCCEEDED(hr))
265     {
266         pDesc->Format = d3dformat_from_wined3dformat(wined3ddesc.format);
267         pDesc->Type = wined3ddesc.resource_type;
268         pDesc->Usage = wined3ddesc.usage;
269         pDesc->Pool = wined3ddesc.pool;
270         pDesc->MultiSampleType = wined3ddesc.multisample_type;
271         pDesc->MultiSampleQuality = wined3ddesc.multisample_quality;
272         pDesc->Width = wined3ddesc.width;
273         pDesc->Height = wined3ddesc.height;
274     }
275
276     return hr;
277 }
278
279 static HRESULT WINAPI IDirect3DTexture9Impl_GetSurfaceLevel(LPDIRECT3DTEXTURE9 iface, UINT Level, IDirect3DSurface9** ppSurfaceLevel) {
280     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
281     HRESULT hrc = D3D_OK;
282     IWineD3DSurface *mySurface = NULL;
283
284     TRACE("(%p) Relay\n", This);
285
286     wined3d_mutex_lock();
287     hrc = IWineD3DTexture_GetSurfaceLevel(This->wineD3DTexture, Level, &mySurface);
288     if (hrc == D3D_OK && NULL != ppSurfaceLevel) {
289        IWineD3DSurface_GetParent(mySurface, (IUnknown **)ppSurfaceLevel);
290        IWineD3DSurface_Release(mySurface);
291     }
292     wined3d_mutex_unlock();
293
294     return hrc;
295 }
296
297 static HRESULT WINAPI IDirect3DTexture9Impl_LockRect(LPDIRECT3DTEXTURE9 iface, UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
298     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
299     HRESULT hr;
300     TRACE("(%p) Relay\n", This);
301
302     wined3d_mutex_lock();
303     hr = IWineD3DTexture_LockRect(This->wineD3DTexture, Level, (WINED3DLOCKED_RECT *) pLockedRect, pRect, Flags);
304     wined3d_mutex_unlock();
305
306     return hr;
307 }
308
309 static HRESULT WINAPI IDirect3DTexture9Impl_UnlockRect(LPDIRECT3DTEXTURE9 iface, UINT Level) {
310     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
311     HRESULT hr;
312     TRACE("(%p) Relay\n", This);
313
314     wined3d_mutex_lock();
315     hr = IWineD3DTexture_UnlockRect(This->wineD3DTexture, Level);
316     wined3d_mutex_unlock();
317
318     return hr;
319 }
320
321 static HRESULT WINAPI IDirect3DTexture9Impl_AddDirtyRect(LPDIRECT3DTEXTURE9 iface, CONST RECT* pDirtyRect) {
322     IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface;
323     HRESULT hr;
324     TRACE("(%p) Relay\n", This);
325
326     wined3d_mutex_lock();
327     hr = IWineD3DTexture_AddDirtyRect(This->wineD3DTexture, pDirtyRect);
328     wined3d_mutex_unlock();
329
330     return hr;
331 }
332
333 static const IDirect3DTexture9Vtbl Direct3DTexture9_Vtbl =
334 {
335     /* IUnknown */
336     IDirect3DTexture9Impl_QueryInterface,
337     IDirect3DTexture9Impl_AddRef,
338     IDirect3DTexture9Impl_Release,
339      /* IDirect3DResource9 */
340     IDirect3DTexture9Impl_GetDevice,
341     IDirect3DTexture9Impl_SetPrivateData,
342     IDirect3DTexture9Impl_GetPrivateData,
343     IDirect3DTexture9Impl_FreePrivateData,
344     IDirect3DTexture9Impl_SetPriority,
345     IDirect3DTexture9Impl_GetPriority,
346     IDirect3DTexture9Impl_PreLoad,
347     IDirect3DTexture9Impl_GetType,
348     /* IDirect3dBaseTexture9 */
349     IDirect3DTexture9Impl_SetLOD,
350     IDirect3DTexture9Impl_GetLOD,
351     IDirect3DTexture9Impl_GetLevelCount,
352     IDirect3DTexture9Impl_SetAutoGenFilterType,
353     IDirect3DTexture9Impl_GetAutoGenFilterType,
354     IDirect3DTexture9Impl_GenerateMipSubLevels,
355     /* IDirect3DTexture9 */
356     IDirect3DTexture9Impl_GetLevelDesc,
357     IDirect3DTexture9Impl_GetSurfaceLevel,
358     IDirect3DTexture9Impl_LockRect,
359     IDirect3DTexture9Impl_UnlockRect,
360     IDirect3DTexture9Impl_AddDirtyRect
361 };
362
363 static void STDMETHODCALLTYPE d3d9_texture_wined3d_object_destroyed(void *parent)
364 {
365     HeapFree(GetProcessHeap(), 0, parent);
366 }
367
368 static const struct wined3d_parent_ops d3d9_texture_wined3d_parent_ops =
369 {
370     d3d9_texture_wined3d_object_destroyed,
371 };
372
373 HRESULT texture_init(IDirect3DTexture9Impl *texture, IDirect3DDevice9Impl *device,
374         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
375 {
376     HRESULT hr;
377
378     texture->lpVtbl = &Direct3DTexture9_Vtbl;
379     texture->ref = 1;
380
381     wined3d_mutex_lock();
382     hr = IWineD3DDevice_CreateTexture(device->WineD3DDevice, width, height, levels,
383             usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool,
384             &texture->wineD3DTexture, (IUnknown *)texture, &d3d9_texture_wined3d_parent_ops);
385     wined3d_mutex_unlock();
386     if (FAILED(hr))
387     {
388         WARN("Failed to create wined3d texture, hr %#x.\n", hr);
389         return hr;
390     }
391
392     texture->parentDevice = (IDirect3DDevice9Ex *)device;
393     IDirect3DDevice9Ex_AddRef(texture->parentDevice);
394
395     return D3D_OK;
396 }