d3d9: Properly retrieve an interface pointer in d3d9_texture_3d_GetVolumeLevel().
[wine] / dlls / d3d9 / texture.c
1 /*
2  * Copyright 2002-2005 Jason Edmeades
3  * Copyright 2002-2005 Raphael Junqueira
4  * Copyright 2005 Oliver Stieber
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "d3d9_private.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
25
26 static inline struct d3d9_texture *impl_from_IDirect3DTexture9(IDirect3DTexture9 *iface)
27 {
28     return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
29 }
30
31 static inline struct d3d9_texture *impl_from_IDirect3DCubeTexture9(IDirect3DCubeTexture9 *iface)
32 {
33     return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
34 }
35
36 static inline struct d3d9_texture *impl_from_IDirect3DVolumeTexture9(IDirect3DVolumeTexture9 *iface)
37 {
38     return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
39 }
40
41 static HRESULT WINAPI d3d9_texture_2d_QueryInterface(IDirect3DTexture9 *iface, REFIID riid, void **out)
42 {
43     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
44
45     if (IsEqualGUID(riid, &IID_IDirect3DTexture9)
46             || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9)
47             || IsEqualGUID(riid, &IID_IDirect3DResource9)
48             || IsEqualGUID(riid, &IID_IUnknown))
49     {
50         IDirect3DTexture9_AddRef(iface);
51         *out = iface;
52         return S_OK;
53     }
54
55     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
56
57     *out = NULL;
58     return E_NOINTERFACE;
59 }
60
61 static ULONG WINAPI d3d9_texture_2d_AddRef(IDirect3DTexture9 *iface)
62 {
63     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
64     ULONG ref = InterlockedIncrement(&texture->refcount);
65
66     TRACE("%p increasing refcount to %u.\n", iface, ref);
67
68     if (ref == 1)
69     {
70         IDirect3DDevice9Ex_AddRef(texture->parent_device);
71         wined3d_mutex_lock();
72         wined3d_texture_incref(texture->wined3d_texture);
73         wined3d_mutex_unlock();
74     }
75
76     return ref;
77 }
78
79 static ULONG WINAPI d3d9_texture_2d_Release(IDirect3DTexture9 *iface)
80 {
81     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
82     ULONG ref = InterlockedDecrement(&texture->refcount);
83
84     TRACE("%p decreasing refcount to %u.\n", iface, ref);
85
86     if (!ref)
87     {
88         IDirect3DDevice9Ex *parent_device = texture->parent_device;
89
90         wined3d_mutex_lock();
91         wined3d_texture_decref(texture->wined3d_texture);
92         wined3d_mutex_unlock();
93
94         /* Release the device last, as it may cause the device to be destroyed. */
95         IDirect3DDevice9Ex_Release(parent_device);
96     }
97     return ref;
98 }
99
100 static HRESULT WINAPI d3d9_texture_2d_GetDevice(IDirect3DTexture9 *iface, IDirect3DDevice9 **device)
101 {
102     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
103
104     TRACE("iface %p, device %p.\n", iface, device);
105
106     *device = (IDirect3DDevice9 *)texture->parent_device;
107     IDirect3DDevice9_AddRef(*device);
108
109     TRACE("Returning device %p.\n", *device);
110
111     return D3D_OK;
112 }
113
114 static HRESULT WINAPI d3d9_texture_2d_SetPrivateData(IDirect3DTexture9 *iface,
115         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
116 {
117     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
118     struct wined3d_resource *resource;
119     HRESULT hr;
120
121     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
122             iface, debugstr_guid(guid), data, data_size, flags);
123
124     wined3d_mutex_lock();
125     resource = wined3d_texture_get_resource(texture->wined3d_texture);
126     hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
127     wined3d_mutex_unlock();
128
129     return hr;
130 }
131
132 static HRESULT WINAPI d3d9_texture_2d_GetPrivateData(IDirect3DTexture9 *iface,
133         REFGUID guid, void *data, DWORD *data_size)
134 {
135     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
136     struct wined3d_resource *resource;
137     HRESULT hr;
138
139     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
140             iface, debugstr_guid(guid), data, data_size);
141
142     wined3d_mutex_lock();
143     resource = wined3d_texture_get_resource(texture->wined3d_texture);
144     hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
145     wined3d_mutex_unlock();
146
147     return hr;
148 }
149
150 static HRESULT WINAPI d3d9_texture_2d_FreePrivateData(IDirect3DTexture9 *iface, REFGUID guid)
151 {
152     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
153     struct wined3d_resource *resource;
154     HRESULT hr;
155
156     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
157
158     wined3d_mutex_lock();
159     resource = wined3d_texture_get_resource(texture->wined3d_texture);
160     hr = wined3d_resource_free_private_data(resource, guid);
161     wined3d_mutex_unlock();
162
163     return hr;
164 }
165
166 static DWORD WINAPI d3d9_texture_2d_SetPriority(IDirect3DTexture9 *iface, DWORD priority)
167 {
168     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
169     DWORD ret;
170
171     TRACE("iface %p, priority %u.\n", iface, priority);
172
173     wined3d_mutex_lock();
174     ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
175     wined3d_mutex_unlock();
176
177     return ret;
178 }
179
180 static DWORD WINAPI d3d9_texture_2d_GetPriority(IDirect3DTexture9 *iface)
181 {
182     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
183     DWORD ret;
184
185     TRACE("iface %p.\n", iface);
186
187     wined3d_mutex_lock();
188     ret = wined3d_texture_get_priority(texture->wined3d_texture);
189     wined3d_mutex_unlock();
190
191     return ret;
192 }
193
194 static void WINAPI d3d9_texture_2d_PreLoad(IDirect3DTexture9 *iface)
195 {
196     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
197
198     TRACE("iface %p.\n", iface);
199
200     wined3d_mutex_lock();
201     wined3d_texture_preload(texture->wined3d_texture);
202     wined3d_mutex_unlock();
203 }
204
205 static D3DRESOURCETYPE WINAPI d3d9_texture_2d_GetType(IDirect3DTexture9 *iface)
206 {
207     TRACE("iface %p.\n", iface);
208
209     return D3DRTYPE_TEXTURE;
210 }
211
212 static DWORD WINAPI d3d9_texture_2d_SetLOD(IDirect3DTexture9 *iface, DWORD lod)
213 {
214     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
215     DWORD ret;
216
217     TRACE("iface %p, lod %u.\n", iface, lod);
218
219     wined3d_mutex_lock();
220     ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
221     wined3d_mutex_unlock();
222
223     return ret;
224 }
225
226 static DWORD WINAPI d3d9_texture_2d_GetLOD(IDirect3DTexture9 *iface)
227 {
228     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
229     DWORD ret;
230
231     TRACE("iface %p.\n", iface);
232
233     wined3d_mutex_lock();
234     ret = wined3d_texture_get_lod(texture->wined3d_texture);
235     wined3d_mutex_unlock();
236
237     return ret;
238 }
239
240 static DWORD WINAPI d3d9_texture_2d_GetLevelCount(IDirect3DTexture9 *iface)
241 {
242     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
243     DWORD ret;
244
245     TRACE("iface %p.\n", iface);
246
247     wined3d_mutex_lock();
248     ret = wined3d_texture_get_level_count(texture->wined3d_texture);
249     wined3d_mutex_unlock();
250
251     return ret;
252 }
253
254 static HRESULT WINAPI d3d9_texture_2d_SetAutoGenFilterType(IDirect3DTexture9 *iface, D3DTEXTUREFILTERTYPE filter_type)
255 {
256     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
257     HRESULT hr;
258
259     TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
260
261     wined3d_mutex_lock();
262     hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
263             (enum wined3d_texture_filter_type)filter_type);
264     wined3d_mutex_unlock();
265
266     return hr;
267 }
268
269 static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_2d_GetAutoGenFilterType(IDirect3DTexture9 *iface)
270 {
271     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
272     D3DTEXTUREFILTERTYPE ret;
273
274     TRACE("iface %p.\n", iface);
275
276     wined3d_mutex_lock();
277     ret = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
278     wined3d_mutex_unlock();
279
280     return ret;
281 }
282
283 static void WINAPI d3d9_texture_2d_GenerateMipSubLevels(IDirect3DTexture9 *iface)
284 {
285     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
286
287     TRACE("iface %p.\n", iface);
288
289     wined3d_mutex_lock();
290     wined3d_texture_generate_mipmaps(texture->wined3d_texture);
291     wined3d_mutex_unlock();
292 }
293
294 static HRESULT WINAPI d3d9_texture_2d_GetLevelDesc(IDirect3DTexture9 *iface, UINT level, D3DSURFACE_DESC *desc)
295 {
296     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
297     struct wined3d_resource *sub_resource;
298     HRESULT hr = D3D_OK;
299
300     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
301
302     wined3d_mutex_lock();
303     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
304         hr = D3DERR_INVALIDCALL;
305     else
306     {
307         struct wined3d_resource_desc wined3d_desc;
308
309         wined3d_resource_get_desc(sub_resource, &wined3d_desc);
310         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
311         desc->Type = wined3d_desc.resource_type;
312         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
313         desc->Pool = wined3d_desc.pool;
314         desc->MultiSampleType = wined3d_desc.multisample_type;
315         desc->MultiSampleQuality = wined3d_desc.multisample_quality;
316         desc->Width = wined3d_desc.width;
317         desc->Height = wined3d_desc.height;
318     }
319     wined3d_mutex_unlock();
320
321     return hr;
322 }
323
324 static HRESULT WINAPI d3d9_texture_2d_GetSurfaceLevel(IDirect3DTexture9 *iface,
325         UINT level, IDirect3DSurface9 **surface)
326 {
327     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
328     struct wined3d_resource *sub_resource;
329     IDirect3DSurface9Impl *surface_impl;
330
331     TRACE("iface %p, level %u, surface %p.\n", iface, level, surface);
332
333     wined3d_mutex_lock();
334     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
335     {
336         wined3d_mutex_unlock();
337         return D3DERR_INVALIDCALL;
338     }
339
340     surface_impl = wined3d_resource_get_parent(sub_resource);
341     *surface = &surface_impl->IDirect3DSurface9_iface;
342     IDirect3DSurface9_AddRef(*surface);
343     wined3d_mutex_unlock();
344
345     return D3D_OK;
346 }
347
348 static HRESULT WINAPI d3d9_texture_2d_LockRect(IDirect3DTexture9 *iface,
349         UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
350 {
351     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
352     struct wined3d_resource *sub_resource;
353     IDirect3DSurface9Impl *surface_impl;
354     HRESULT hr;
355
356     TRACE("iface %p, level %u, locked_rect %p, rect %p, flags %#x.\n",
357             iface, level, locked_rect, rect, flags);
358
359     wined3d_mutex_lock();
360     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
361         hr = D3DERR_INVALIDCALL;
362     else
363     {
364         surface_impl = wined3d_resource_get_parent(sub_resource);
365         hr = IDirect3DSurface9_LockRect(&surface_impl->IDirect3DSurface9_iface, locked_rect, rect, flags);
366     }
367     wined3d_mutex_unlock();
368
369     return hr;
370 }
371
372 static HRESULT WINAPI d3d9_texture_2d_UnlockRect(IDirect3DTexture9 *iface, UINT level)
373 {
374     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
375     struct wined3d_resource *sub_resource;
376     IDirect3DSurface9Impl *surface_impl;
377     HRESULT hr;
378
379     TRACE("iface %p, level %u.\n", iface, level);
380
381     wined3d_mutex_lock();
382     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
383         hr = D3DERR_INVALIDCALL;
384     else
385     {
386         surface_impl = wined3d_resource_get_parent(sub_resource);
387         hr = IDirect3DSurface9_UnlockRect(&surface_impl->IDirect3DSurface9_iface);
388     }
389     wined3d_mutex_unlock();
390
391     return hr;
392 }
393
394 static HRESULT WINAPI d3d9_texture_2d_AddDirtyRect(IDirect3DTexture9 *iface, const RECT *dirty_rect)
395 {
396     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
397     HRESULT hr;
398
399     TRACE("iface %p, dirty_rect %s.\n",
400             iface, wine_dbgstr_rect(dirty_rect));
401
402     wined3d_mutex_lock();
403     if (!dirty_rect)
404         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, NULL);
405     else
406     {
407         struct wined3d_box dirty_region;
408
409         dirty_region.left = dirty_rect->left;
410         dirty_region.top = dirty_rect->top;
411         dirty_region.right = dirty_rect->right;
412         dirty_region.bottom = dirty_rect->bottom;
413         dirty_region.front = 0;
414         dirty_region.back = 1;
415         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, &dirty_region);
416     }
417     wined3d_mutex_unlock();
418
419     return hr;
420 }
421
422 static const IDirect3DTexture9Vtbl d3d9_texture_2d_vtbl =
423 {
424     /* IUnknown */
425     d3d9_texture_2d_QueryInterface,
426     d3d9_texture_2d_AddRef,
427     d3d9_texture_2d_Release,
428      /* IDirect3DResource9 */
429     d3d9_texture_2d_GetDevice,
430     d3d9_texture_2d_SetPrivateData,
431     d3d9_texture_2d_GetPrivateData,
432     d3d9_texture_2d_FreePrivateData,
433     d3d9_texture_2d_SetPriority,
434     d3d9_texture_2d_GetPriority,
435     d3d9_texture_2d_PreLoad,
436     d3d9_texture_2d_GetType,
437     /* IDirect3dBaseTexture9 */
438     d3d9_texture_2d_SetLOD,
439     d3d9_texture_2d_GetLOD,
440     d3d9_texture_2d_GetLevelCount,
441     d3d9_texture_2d_SetAutoGenFilterType,
442     d3d9_texture_2d_GetAutoGenFilterType,
443     d3d9_texture_2d_GenerateMipSubLevels,
444     /* IDirect3DTexture9 */
445     d3d9_texture_2d_GetLevelDesc,
446     d3d9_texture_2d_GetSurfaceLevel,
447     d3d9_texture_2d_LockRect,
448     d3d9_texture_2d_UnlockRect,
449     d3d9_texture_2d_AddDirtyRect,
450 };
451
452 static HRESULT WINAPI d3d9_texture_cube_QueryInterface(IDirect3DCubeTexture9 *iface, REFIID riid, void **out)
453 {
454     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
455
456     if (IsEqualGUID(riid, &IID_IDirect3DCubeTexture9)
457             || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9)
458             || IsEqualGUID(riid, &IID_IDirect3DResource9)
459             || IsEqualGUID(riid, &IID_IUnknown))
460     {
461         IDirect3DCubeTexture9_AddRef(iface);
462         *out = iface;
463         return S_OK;
464     }
465
466     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
467
468     *out = NULL;
469     return E_NOINTERFACE;
470 }
471
472 static ULONG WINAPI d3d9_texture_cube_AddRef(IDirect3DCubeTexture9 *iface)
473 {
474     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
475     ULONG ref = InterlockedIncrement(&texture->refcount);
476
477     TRACE("%p increasing refcount to %u.\n", iface, ref);
478
479     if (ref == 1)
480     {
481         IDirect3DDevice9Ex_AddRef(texture->parent_device);
482         wined3d_mutex_lock();
483         wined3d_texture_incref(texture->wined3d_texture);
484         wined3d_mutex_unlock();
485     }
486
487     return ref;
488 }
489
490 static ULONG WINAPI d3d9_texture_cube_Release(IDirect3DCubeTexture9 *iface)
491 {
492     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
493     ULONG ref = InterlockedDecrement(&texture->refcount);
494
495     TRACE("%p decreasing refcount to %u.\n", iface, ref);
496
497     if (!ref)
498     {
499         IDirect3DDevice9Ex *parent_device = texture->parent_device;
500
501         TRACE("Releasing child %p.\n", texture->wined3d_texture);
502
503         wined3d_mutex_lock();
504         wined3d_texture_decref(texture->wined3d_texture);
505         wined3d_mutex_unlock();
506
507         /* Release the device last, as it may cause the device to be destroyed. */
508         IDirect3DDevice9Ex_Release(parent_device);
509     }
510     return ref;
511 }
512
513 static HRESULT WINAPI d3d9_texture_cube_GetDevice(IDirect3DCubeTexture9 *iface, IDirect3DDevice9 **device)
514 {
515     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
516
517     TRACE("iface %p, device %p.\n", iface, device);
518
519     *device = (IDirect3DDevice9 *)texture->parent_device;
520     IDirect3DDevice9_AddRef(*device);
521
522     TRACE("Returning device %p.\n", *device);
523
524     return D3D_OK;
525 }
526
527 static HRESULT WINAPI d3d9_texture_cube_SetPrivateData(IDirect3DCubeTexture9 *iface,
528         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
529 {
530     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
531     struct wined3d_resource *resource;
532     HRESULT hr;
533
534     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
535             iface, debugstr_guid(guid), data, data_size, flags);
536
537     wined3d_mutex_lock();
538     resource = wined3d_texture_get_resource(texture->wined3d_texture);
539     hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
540     wined3d_mutex_unlock();
541
542     return hr;
543 }
544
545 static HRESULT WINAPI d3d9_texture_cube_GetPrivateData(IDirect3DCubeTexture9 *iface,
546         REFGUID guid, void *data, DWORD *data_size)
547 {
548     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
549     struct wined3d_resource *resource;
550     HRESULT hr;
551
552     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
553             iface, debugstr_guid(guid), data, data_size);
554
555     wined3d_mutex_lock();
556     resource = wined3d_texture_get_resource(texture->wined3d_texture);
557     hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
558     wined3d_mutex_unlock();
559
560     return hr;
561 }
562
563 static HRESULT WINAPI d3d9_texture_cube_FreePrivateData(IDirect3DCubeTexture9 *iface, REFGUID guid)
564 {
565     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
566     struct wined3d_resource *resource;
567     HRESULT hr;
568
569     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
570
571     wined3d_mutex_lock();
572     resource = wined3d_texture_get_resource(texture->wined3d_texture);
573     hr = wined3d_resource_free_private_data(resource, guid);
574     wined3d_mutex_unlock();
575
576     return hr;
577 }
578
579 static DWORD WINAPI d3d9_texture_cube_SetPriority(IDirect3DCubeTexture9 *iface, DWORD priority)
580 {
581     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
582     DWORD ret;
583
584     TRACE("iface %p, priority %u.\n", iface, priority);
585
586     wined3d_mutex_lock();
587     ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
588     wined3d_mutex_unlock();
589
590     return ret;
591 }
592
593 static DWORD WINAPI d3d9_texture_cube_GetPriority(IDirect3DCubeTexture9 *iface)
594 {
595     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
596     DWORD ret;
597
598     TRACE("iface %p.\n", iface);
599
600     wined3d_mutex_lock();
601     ret = wined3d_texture_get_priority(texture->wined3d_texture);
602     wined3d_mutex_unlock();
603
604     return ret;
605 }
606
607 static void WINAPI d3d9_texture_cube_PreLoad(IDirect3DCubeTexture9 *iface)
608 {
609     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
610
611     TRACE("iface %p.\n", iface);
612
613     wined3d_mutex_lock();
614     wined3d_texture_preload(texture->wined3d_texture);
615     wined3d_mutex_unlock();
616 }
617
618 static D3DRESOURCETYPE WINAPI d3d9_texture_cube_GetType(IDirect3DCubeTexture9 *iface)
619 {
620     TRACE("iface %p.\n", iface);
621
622     return D3DRTYPE_CUBETEXTURE;
623 }
624
625 static DWORD WINAPI d3d9_texture_cube_SetLOD(IDirect3DCubeTexture9 *iface, DWORD lod)
626 {
627     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
628     DWORD ret;
629
630     TRACE("iface %p, lod %u.\n", iface, lod);
631
632     wined3d_mutex_lock();
633     ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
634     wined3d_mutex_unlock();
635
636     return ret;
637 }
638
639 static DWORD WINAPI d3d9_texture_cube_GetLOD(IDirect3DCubeTexture9 *iface)
640 {
641     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
642     DWORD ret;
643
644     TRACE("iface %p.\n", iface);
645
646     wined3d_mutex_lock();
647     ret = wined3d_texture_get_lod(texture->wined3d_texture);
648     wined3d_mutex_unlock();
649
650     return ret;
651 }
652
653 static DWORD WINAPI d3d9_texture_cube_GetLevelCount(IDirect3DCubeTexture9 *iface)
654 {
655     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
656     DWORD ret;
657
658     TRACE("iface %p.\n", iface);
659
660     wined3d_mutex_lock();
661     ret = wined3d_texture_get_level_count(texture->wined3d_texture);
662     wined3d_mutex_unlock();
663
664     return ret;
665 }
666
667 static HRESULT WINAPI d3d9_texture_cube_SetAutoGenFilterType(IDirect3DCubeTexture9 *iface,
668         D3DTEXTUREFILTERTYPE filter_type)
669 {
670     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
671     HRESULT hr;
672
673     TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
674
675     wined3d_mutex_lock();
676     hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
677             (enum wined3d_texture_filter_type)filter_type);
678     wined3d_mutex_unlock();
679
680     return hr;
681 }
682
683 static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_cube_GetAutoGenFilterType(IDirect3DCubeTexture9 *iface)
684 {
685     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
686     D3DTEXTUREFILTERTYPE ret;
687
688     TRACE("iface %p.\n", iface);
689
690     wined3d_mutex_lock();
691     ret = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
692     wined3d_mutex_unlock();
693
694     return ret;
695 }
696
697 static void WINAPI d3d9_texture_cube_GenerateMipSubLevels(IDirect3DCubeTexture9 *iface)
698 {
699     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
700
701     TRACE("iface %p.\n", iface);
702
703     wined3d_mutex_lock();
704     wined3d_texture_generate_mipmaps(texture->wined3d_texture);
705     wined3d_mutex_unlock();
706 }
707
708 static HRESULT WINAPI d3d9_texture_cube_GetLevelDesc(IDirect3DCubeTexture9 *iface, UINT level, D3DSURFACE_DESC *desc)
709 {
710     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
711     struct wined3d_resource *sub_resource;
712     HRESULT hr = D3D_OK;
713
714     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
715
716     wined3d_mutex_lock();
717     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
718         hr = D3DERR_INVALIDCALL;
719     else
720     {
721         struct wined3d_resource_desc wined3d_desc;
722
723         wined3d_resource_get_desc(sub_resource, &wined3d_desc);
724         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
725         desc->Type = wined3d_desc.resource_type;
726         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
727         desc->Pool = wined3d_desc.pool;
728         desc->MultiSampleType = wined3d_desc.multisample_type;
729         desc->MultiSampleQuality = wined3d_desc.multisample_quality;
730         desc->Width = wined3d_desc.width;
731         desc->Height = wined3d_desc.height;
732     }
733     wined3d_mutex_unlock();
734
735     return hr;
736 }
737
738 static HRESULT WINAPI d3d9_texture_cube_GetCubeMapSurface(IDirect3DCubeTexture9 *iface,
739         D3DCUBEMAP_FACES face, UINT level, IDirect3DSurface9 **surface)
740 {
741     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
742     struct wined3d_resource *sub_resource;
743     IDirect3DSurface9Impl *surface_impl;
744     UINT sub_resource_idx;
745
746     TRACE("iface %p, face %#x, level %u, surface %p.\n", iface, face, level, surface);
747
748     wined3d_mutex_lock();
749     sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
750     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
751     {
752         wined3d_mutex_unlock();
753         return D3DERR_INVALIDCALL;
754     }
755
756     surface_impl = wined3d_resource_get_parent(sub_resource);
757     *surface = &surface_impl->IDirect3DSurface9_iface;
758     IDirect3DSurface9_AddRef(*surface);
759     wined3d_mutex_unlock();
760
761     return D3D_OK;
762 }
763
764 static HRESULT WINAPI d3d9_texture_cube_LockRect(IDirect3DCubeTexture9 *iface,
765         D3DCUBEMAP_FACES face, UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect,
766         DWORD flags)
767 {
768     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
769     struct wined3d_resource *sub_resource;
770     IDirect3DSurface9Impl *surface_impl;
771     UINT sub_resource_idx;
772     HRESULT hr;
773
774     TRACE("iface %p, face %#x, level %u, locked_rect %p, rect %p, flags %#x.\n",
775             iface, face, level, locked_rect, rect, flags);
776
777     wined3d_mutex_lock();
778     sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
779     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
780         hr = D3DERR_INVALIDCALL;
781     else
782     {
783         surface_impl = wined3d_resource_get_parent(sub_resource);
784         hr = IDirect3DSurface9_LockRect(&surface_impl->IDirect3DSurface9_iface, locked_rect, rect, flags);
785     }
786     wined3d_mutex_unlock();
787
788     return hr;
789 }
790
791 static HRESULT WINAPI d3d9_texture_cube_UnlockRect(IDirect3DCubeTexture9 *iface,
792         D3DCUBEMAP_FACES face, UINT level)
793 {
794     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
795     struct wined3d_resource *sub_resource;
796     IDirect3DSurface9Impl *surface_impl;
797     UINT sub_resource_idx;
798     HRESULT hr;
799
800     TRACE("iface %p, face %#x, level %u.\n", iface, face, level);
801
802     wined3d_mutex_lock();
803     sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
804     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
805         hr = D3DERR_INVALIDCALL;
806     else
807     {
808         surface_impl = wined3d_resource_get_parent(sub_resource);
809         hr = IDirect3DSurface9_UnlockRect(&surface_impl->IDirect3DSurface9_iface);
810     }
811     wined3d_mutex_unlock();
812
813     return hr;
814 }
815
816 static HRESULT  WINAPI d3d9_texture_cube_AddDirtyRect(IDirect3DCubeTexture9 *iface,
817         D3DCUBEMAP_FACES face, const RECT *dirty_rect)
818 {
819     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
820     HRESULT hr;
821
822     TRACE("iface %p, face %#x, dirty_rect %s.\n",
823             iface, face, wine_dbgstr_rect(dirty_rect));
824
825     wined3d_mutex_lock();
826     if (!dirty_rect)
827         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, NULL);
828     else
829     {
830         struct wined3d_box dirty_region;
831
832         dirty_region.left = dirty_rect->left;
833         dirty_region.top = dirty_rect->top;
834         dirty_region.right = dirty_rect->right;
835         dirty_region.bottom = dirty_rect->bottom;
836         dirty_region.front = 0;
837         dirty_region.back = 1;
838         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, &dirty_region);
839     }
840     wined3d_mutex_unlock();
841
842     return hr;
843 }
844
845 static const IDirect3DCubeTexture9Vtbl d3d9_texture_cube_vtbl =
846 {
847     /* IUnknown */
848     d3d9_texture_cube_QueryInterface,
849     d3d9_texture_cube_AddRef,
850     d3d9_texture_cube_Release,
851     /* IDirect3DResource9 */
852     d3d9_texture_cube_GetDevice,
853     d3d9_texture_cube_SetPrivateData,
854     d3d9_texture_cube_GetPrivateData,
855     d3d9_texture_cube_FreePrivateData,
856     d3d9_texture_cube_SetPriority,
857     d3d9_texture_cube_GetPriority,
858     d3d9_texture_cube_PreLoad,
859     d3d9_texture_cube_GetType,
860     /* IDirect3DBaseTexture9 */
861     d3d9_texture_cube_SetLOD,
862     d3d9_texture_cube_GetLOD,
863     d3d9_texture_cube_GetLevelCount,
864     d3d9_texture_cube_SetAutoGenFilterType,
865     d3d9_texture_cube_GetAutoGenFilterType,
866     d3d9_texture_cube_GenerateMipSubLevels,
867     /* IDirect3DCubeTexture9 */
868     d3d9_texture_cube_GetLevelDesc,
869     d3d9_texture_cube_GetCubeMapSurface,
870     d3d9_texture_cube_LockRect,
871     d3d9_texture_cube_UnlockRect,
872     d3d9_texture_cube_AddDirtyRect,
873 };
874
875 static HRESULT WINAPI d3d9_texture_3d_QueryInterface(IDirect3DVolumeTexture9 *iface, REFIID riid, void **out)
876 {
877     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
878
879     if (IsEqualGUID(riid, &IID_IDirect3DVolumeTexture9)
880             || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9)
881             || IsEqualGUID(riid, &IID_IDirect3DResource9)
882             || IsEqualGUID(riid, &IID_IUnknown))
883     {
884         IDirect3DVolumeTexture9_AddRef(iface);
885         *out = iface;
886         return S_OK;
887     }
888
889     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
890
891     *out = NULL;
892     return E_NOINTERFACE;
893 }
894
895 static ULONG WINAPI d3d9_texture_3d_AddRef(IDirect3DVolumeTexture9 *iface)
896 {
897     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
898     ULONG ref = InterlockedIncrement(&texture->refcount);
899
900     TRACE("%p increasing refcount to %u.\n", iface, ref);
901
902     if (ref == 1)
903     {
904         IDirect3DDevice9Ex_AddRef(texture->parent_device);
905         wined3d_mutex_lock();
906         wined3d_texture_incref(texture->wined3d_texture);
907         wined3d_mutex_unlock();
908     }
909
910     return ref;
911 }
912
913 static ULONG WINAPI d3d9_texture_3d_Release(IDirect3DVolumeTexture9 *iface)
914 {
915     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
916     ULONG ref = InterlockedDecrement(&texture->refcount);
917
918     TRACE("%p decreasing refcount to %u.\n", iface, ref);
919
920     if (!ref)
921     {
922         IDirect3DDevice9Ex *parent_device = texture->parent_device;
923
924         wined3d_mutex_lock();
925         wined3d_texture_decref(texture->wined3d_texture);
926         wined3d_mutex_unlock();
927
928         /* Release the device last, as it may cause the device to be destroyed. */
929         IDirect3DDevice9Ex_Release(parent_device);
930     }
931     return ref;
932 }
933
934 static HRESULT WINAPI d3d9_texture_3d_GetDevice(IDirect3DVolumeTexture9 *iface, IDirect3DDevice9 **device)
935 {
936     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
937
938     TRACE("iface %p, device %p.\n", iface, device);
939
940     *device = (IDirect3DDevice9 *)texture->parent_device;
941     IDirect3DDevice9_AddRef(*device);
942
943     TRACE("Returning device %p.\n", *device);
944
945     return D3D_OK;
946 }
947
948 static HRESULT WINAPI d3d9_texture_3d_SetPrivateData(IDirect3DVolumeTexture9 *iface,
949         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
950 {
951     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
952     struct wined3d_resource *resource;
953     HRESULT hr;
954
955     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
956             iface, debugstr_guid(guid), data, data_size, flags);
957
958     wined3d_mutex_lock();
959     resource = wined3d_texture_get_resource(texture->wined3d_texture);
960     hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
961     wined3d_mutex_unlock();
962
963     return hr;
964 }
965
966 static HRESULT WINAPI d3d9_texture_3d_GetPrivateData(IDirect3DVolumeTexture9 *iface,
967         REFGUID guid, void *data, DWORD *data_size)
968 {
969     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
970     struct wined3d_resource *resource;
971     HRESULT hr;
972
973     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
974             iface, debugstr_guid(guid), data, data_size);
975
976     wined3d_mutex_lock();
977     resource = wined3d_texture_get_resource(texture->wined3d_texture);
978     hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
979     wined3d_mutex_unlock();
980
981     return hr;
982 }
983
984 static HRESULT WINAPI d3d9_texture_3d_FreePrivateData(IDirect3DVolumeTexture9 *iface, REFGUID guid)
985 {
986     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
987     struct wined3d_resource *resource;
988     HRESULT hr;
989
990     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
991
992     wined3d_mutex_lock();
993     resource = wined3d_texture_get_resource(texture->wined3d_texture);
994     hr = wined3d_resource_free_private_data(resource, guid);
995     wined3d_mutex_unlock();
996
997     return hr;
998 }
999
1000 static DWORD WINAPI d3d9_texture_3d_SetPriority(IDirect3DVolumeTexture9 *iface, DWORD priority)
1001 {
1002     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1003     DWORD ret;
1004
1005     TRACE("iface %p, priority %u.\n", iface, priority);
1006
1007     wined3d_mutex_lock();
1008     ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
1009     wined3d_mutex_unlock();
1010
1011     return ret;
1012 }
1013
1014 static DWORD WINAPI d3d9_texture_3d_GetPriority(IDirect3DVolumeTexture9 *iface)
1015 {
1016     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1017     DWORD ret;
1018
1019     TRACE("iface %p.\n", iface);
1020
1021     wined3d_mutex_lock();
1022     ret = wined3d_texture_get_priority(texture->wined3d_texture);
1023     wined3d_mutex_unlock();
1024
1025     return ret;
1026 }
1027
1028 static void WINAPI d3d9_texture_3d_PreLoad(IDirect3DVolumeTexture9 *iface)
1029 {
1030     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1031
1032     TRACE("iface %p.\n", iface);
1033
1034     wined3d_mutex_lock();
1035     wined3d_texture_preload(texture->wined3d_texture);
1036     wined3d_mutex_unlock();
1037 }
1038
1039 static D3DRESOURCETYPE WINAPI d3d9_texture_3d_GetType(IDirect3DVolumeTexture9 *iface)
1040 {
1041     TRACE("iface %p.\n", iface);
1042
1043     return D3DRTYPE_VOLUMETEXTURE;
1044 }
1045
1046 static DWORD WINAPI d3d9_texture_3d_SetLOD(IDirect3DVolumeTexture9 *iface, DWORD lod)
1047 {
1048     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1049     DWORD ret;
1050
1051     TRACE("iface %p, lod %u.\n", iface, lod);
1052
1053     wined3d_mutex_lock();
1054     ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
1055     wined3d_mutex_unlock();
1056
1057     return ret;
1058 }
1059
1060 static DWORD WINAPI d3d9_texture_3d_GetLOD(IDirect3DVolumeTexture9 *iface)
1061 {
1062     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1063     DWORD ret;
1064
1065     TRACE("iface %p.\n", iface);
1066
1067     wined3d_mutex_lock();
1068     ret = wined3d_texture_get_lod(texture->wined3d_texture);
1069     wined3d_mutex_unlock();
1070
1071     return ret;
1072 }
1073
1074 static DWORD WINAPI d3d9_texture_3d_GetLevelCount(IDirect3DVolumeTexture9 *iface)
1075 {
1076     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1077     DWORD ret;
1078
1079     TRACE("iface %p.\n", iface);
1080
1081     wined3d_mutex_lock();
1082     ret = wined3d_texture_get_level_count(texture->wined3d_texture);
1083     wined3d_mutex_unlock();
1084
1085     return ret;
1086 }
1087
1088 static HRESULT WINAPI d3d9_texture_3d_SetAutoGenFilterType(IDirect3DVolumeTexture9 *iface,
1089         D3DTEXTUREFILTERTYPE filter_type)
1090 {
1091     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1092     HRESULT hr;
1093
1094     TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
1095
1096     wined3d_mutex_lock();
1097     hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
1098             (enum wined3d_texture_filter_type)filter_type);
1099     wined3d_mutex_unlock();
1100
1101     return hr;
1102 }
1103
1104 static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_3d_GetAutoGenFilterType(IDirect3DVolumeTexture9 *iface)
1105 {
1106     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1107     D3DTEXTUREFILTERTYPE filter_type;
1108
1109     TRACE("iface %p.\n", iface);
1110
1111     wined3d_mutex_lock();
1112     filter_type = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
1113     wined3d_mutex_unlock();
1114
1115     return filter_type;
1116 }
1117
1118 static void WINAPI d3d9_texture_3d_GenerateMipSubLevels(IDirect3DVolumeTexture9 *iface)
1119 {
1120     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1121
1122     TRACE("iface %p.\n", iface);
1123
1124     wined3d_mutex_lock();
1125     wined3d_texture_generate_mipmaps(texture->wined3d_texture);
1126     wined3d_mutex_unlock();
1127 }
1128
1129 static HRESULT WINAPI d3d9_texture_3d_GetLevelDesc(IDirect3DVolumeTexture9 *iface, UINT level, D3DVOLUME_DESC *desc)
1130 {
1131     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1132     struct wined3d_resource *sub_resource;
1133     HRESULT hr = D3D_OK;
1134
1135     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
1136
1137     wined3d_mutex_lock();
1138     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
1139         hr = D3DERR_INVALIDCALL;
1140     else
1141     {
1142         struct wined3d_resource_desc wined3d_desc;
1143
1144         wined3d_resource_get_desc(sub_resource, &wined3d_desc);
1145         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
1146         desc->Type = wined3d_desc.resource_type;
1147         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
1148         desc->Pool = wined3d_desc.pool;
1149         desc->Width = wined3d_desc.width;
1150         desc->Height = wined3d_desc.height;
1151         desc->Depth = wined3d_desc.depth;
1152     }
1153     wined3d_mutex_unlock();
1154
1155     return hr;
1156 }
1157
1158 static HRESULT WINAPI d3d9_texture_3d_GetVolumeLevel(IDirect3DVolumeTexture9 *iface,
1159         UINT level, IDirect3DVolume9 **volume)
1160 {
1161     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1162     struct wined3d_resource *sub_resource;
1163     IDirect3DVolume9Impl *volume_impl;
1164
1165     TRACE("iface %p, level %u, volume %p.\n", iface, level, volume);
1166
1167     wined3d_mutex_lock();
1168     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
1169     {
1170         wined3d_mutex_unlock();
1171         return D3DERR_INVALIDCALL;
1172     }
1173
1174     volume_impl = wined3d_resource_get_parent(sub_resource);
1175     *volume = &volume_impl->IDirect3DVolume9_iface;
1176     IDirect3DVolume9_AddRef(*volume);
1177     wined3d_mutex_unlock();
1178
1179     return D3D_OK;
1180 }
1181
1182 static HRESULT WINAPI d3d9_texture_3d_LockBox(IDirect3DVolumeTexture9 *iface,
1183         UINT level, D3DLOCKED_BOX *locked_box, const D3DBOX *box, DWORD flags)
1184 {
1185     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1186     struct wined3d_resource *sub_resource;
1187     HRESULT hr;
1188
1189     TRACE("iface %p, level %u, locked_box %p, box %p, flags %#x.\n",
1190             iface, level, locked_box, box, flags);
1191
1192     wined3d_mutex_lock();
1193     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
1194         hr = D3DERR_INVALIDCALL;
1195     else
1196         hr = IDirect3DVolume9_LockBox((IDirect3DVolume9 *)wined3d_resource_get_parent(sub_resource),
1197                 locked_box, box, flags);
1198     wined3d_mutex_unlock();
1199
1200     return hr;
1201 }
1202
1203 static HRESULT WINAPI d3d9_texture_3d_UnlockBox(IDirect3DVolumeTexture9 *iface, UINT level)
1204 {
1205     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1206     struct wined3d_resource *sub_resource;
1207     HRESULT hr;
1208
1209     TRACE("iface %p, level %u.\n", iface, level);
1210
1211     wined3d_mutex_lock();
1212     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
1213         hr = D3DERR_INVALIDCALL;
1214     else
1215         hr = IDirect3DVolume9_UnlockBox((IDirect3DVolume9 *)wined3d_resource_get_parent(sub_resource));
1216     wined3d_mutex_unlock();
1217
1218     return hr;
1219 }
1220
1221 static HRESULT WINAPI d3d9_texture_3d_AddDirtyBox(IDirect3DVolumeTexture9 *iface, const D3DBOX *dirty_box)
1222 {
1223     struct d3d9_texture *texture = impl_from_IDirect3DVolumeTexture9(iface);
1224     HRESULT hr;
1225
1226     TRACE("iface %p, dirty_box %p.\n", iface, dirty_box);
1227
1228     wined3d_mutex_lock();
1229     hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, (const struct wined3d_box *)dirty_box);
1230     wined3d_mutex_unlock();
1231
1232     return hr;
1233 }
1234
1235
1236 static const IDirect3DVolumeTexture9Vtbl d3d9_texture_3d_vtbl =
1237 {
1238     /* IUnknown */
1239     d3d9_texture_3d_QueryInterface,
1240     d3d9_texture_3d_AddRef,
1241     d3d9_texture_3d_Release,
1242     /* IDirect3DResource9 */
1243     d3d9_texture_3d_GetDevice,
1244     d3d9_texture_3d_SetPrivateData,
1245     d3d9_texture_3d_GetPrivateData,
1246     d3d9_texture_3d_FreePrivateData,
1247     d3d9_texture_3d_SetPriority,
1248     d3d9_texture_3d_GetPriority,
1249     d3d9_texture_3d_PreLoad,
1250     d3d9_texture_3d_GetType,
1251     /* IDirect3DBaseTexture9 */
1252     d3d9_texture_3d_SetLOD,
1253     d3d9_texture_3d_GetLOD,
1254     d3d9_texture_3d_GetLevelCount,
1255     d3d9_texture_3d_SetAutoGenFilterType,
1256     d3d9_texture_3d_GetAutoGenFilterType,
1257     d3d9_texture_3d_GenerateMipSubLevels,
1258     /* IDirect3DVolumeTexture9 */
1259     d3d9_texture_3d_GetLevelDesc,
1260     d3d9_texture_3d_GetVolumeLevel,
1261     d3d9_texture_3d_LockBox,
1262     d3d9_texture_3d_UnlockBox,
1263     d3d9_texture_3d_AddDirtyBox,
1264 };
1265
1266 struct d3d9_texture *unsafe_impl_from_IDirect3DBaseTexture9(IDirect3DBaseTexture9 *iface)
1267 {
1268     if (!iface)
1269         return NULL;
1270     assert(iface->lpVtbl == (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl
1271             || iface->lpVtbl == (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl
1272             || iface->lpVtbl == (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl);
1273     return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
1274 }
1275
1276 static void STDMETHODCALLTYPE d3d9_texture_wined3d_object_destroyed(void *parent)
1277 {
1278     HeapFree(GetProcessHeap(), 0, parent);
1279 }
1280
1281 static const struct wined3d_parent_ops d3d9_texture_wined3d_parent_ops =
1282 {
1283     d3d9_texture_wined3d_object_destroyed,
1284 };
1285
1286 HRESULT texture_init(struct d3d9_texture *texture, IDirect3DDevice9Impl *device,
1287         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
1288 {
1289     HRESULT hr;
1290
1291     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl;
1292     texture->refcount = 1;
1293
1294     wined3d_mutex_lock();
1295     hr = wined3d_texture_create_2d(device->wined3d_device, width, height, levels,
1296             usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool,
1297             texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
1298     wined3d_mutex_unlock();
1299     if (FAILED(hr))
1300     {
1301         WARN("Failed to create wined3d texture, hr %#x.\n", hr);
1302         return hr;
1303     }
1304
1305     texture->parent_device = &device->IDirect3DDevice9Ex_iface;
1306     IDirect3DDevice9Ex_AddRef(texture->parent_device);
1307
1308     return D3D_OK;
1309 }
1310
1311 HRESULT cubetexture_init(struct d3d9_texture *texture, IDirect3DDevice9Impl *device,
1312         UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
1313 {
1314     HRESULT hr;
1315
1316     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl;
1317     texture->refcount = 1;
1318
1319     wined3d_mutex_lock();
1320     hr = wined3d_texture_create_cube(device->wined3d_device, edge_length,
1321             levels, usage, wined3dformat_from_d3dformat(format), pool, texture,
1322             &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
1323     wined3d_mutex_unlock();
1324     if (FAILED(hr))
1325     {
1326         WARN("Failed to create wined3d cube texture, hr %#x.\n", hr);
1327         return hr;
1328     }
1329
1330     texture->parent_device = &device->IDirect3DDevice9Ex_iface;
1331     IDirect3DDevice9Ex_AddRef(texture->parent_device);
1332
1333     return D3D_OK;
1334 }
1335
1336 HRESULT volumetexture_init(struct d3d9_texture *texture, IDirect3DDevice9Impl *device,
1337         UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
1338 {
1339     HRESULT hr;
1340
1341     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_3d_vtbl;
1342     texture->refcount = 1;
1343
1344     wined3d_mutex_lock();
1345     hr = wined3d_texture_create_3d(device->wined3d_device, width, height, depth, levels,
1346             usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool, texture,
1347             &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
1348     wined3d_mutex_unlock();
1349     if (FAILED(hr))
1350     {
1351         WARN("Failed to create wined3d volume texture, hr %#x.\n", hr);
1352         return hr;
1353     }
1354
1355     texture->parent_device = &device->IDirect3DDevice9Ex_iface;
1356     IDirect3DDevice9Ex_AddRef(texture->parent_device);
1357
1358     return D3D_OK;
1359 }