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