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