xref: /reactos/dll/directx/wine/d3d8/texture.c (revision 321bcc05)
1 /*
2  * Copyright 2005 Oliver Stieber
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "d3d8_private.h"
20 
21 static inline struct d3d8_texture *impl_from_IDirect3DTexture8(IDirect3DTexture8 *iface)
22 {
23     return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
24 }
25 
26 static inline struct d3d8_texture *impl_from_IDirect3DCubeTexture8(IDirect3DCubeTexture8 *iface)
27 {
28     return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
29 }
30 
31 static inline struct d3d8_texture *impl_from_IDirect3DVolumeTexture8(IDirect3DVolumeTexture8 *iface)
32 {
33     return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
34 }
35 
36 static HRESULT WINAPI d3d8_texture_2d_QueryInterface(IDirect3DTexture8 *iface, REFIID riid, void **out)
37 {
38     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
39 
40     if (IsEqualGUID(riid, &IID_IDirect3DTexture8)
41             || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8)
42             || IsEqualGUID(riid, &IID_IDirect3DResource8)
43             || IsEqualGUID(riid, &IID_IUnknown))
44     {
45         IDirect3DTexture8_AddRef(iface);
46         *out = iface;
47         return S_OK;
48     }
49 
50     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
51 
52     *out = NULL;
53     return E_NOINTERFACE;
54 }
55 
56 static ULONG WINAPI d3d8_texture_2d_AddRef(IDirect3DTexture8 *iface)
57 {
58     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
59     ULONG ref = InterlockedIncrement(&texture->resource.refcount);
60 
61     TRACE("%p increasing refcount to %u.\n", iface, ref);
62 
63     if (ref == 1)
64     {
65         struct d3d8_surface *surface;
66 
67         IDirect3DDevice8_AddRef(texture->parent_device);
68         wined3d_mutex_lock();
69         LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
70         {
71             wined3d_rendertarget_view_incref(surface->wined3d_rtv);
72         }
73         wined3d_texture_incref(texture->wined3d_texture);
74         wined3d_mutex_unlock();
75     }
76 
77     return ref;
78 }
79 
80 static ULONG WINAPI d3d8_texture_2d_Release(IDirect3DTexture8 *iface)
81 {
82     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
83     ULONG ref = InterlockedDecrement(&texture->resource.refcount);
84 
85     TRACE("%p decreasing refcount to %u.\n", iface, ref);
86 
87     if (!ref)
88     {
89         IDirect3DDevice8 *parent_device = texture->parent_device;
90         struct d3d8_surface *surface;
91 
92         wined3d_mutex_lock();
93         LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
94         {
95             wined3d_rendertarget_view_decref(surface->wined3d_rtv);
96         }
97         wined3d_texture_decref(texture->wined3d_texture);
98         wined3d_mutex_unlock();
99 
100         /* Release the device last, as it may cause the device to be destroyed. */
101         IDirect3DDevice8_Release(parent_device);
102     }
103     return ref;
104 }
105 
106 static HRESULT WINAPI d3d8_texture_2d_GetDevice(IDirect3DTexture8 *iface, IDirect3DDevice8 **device)
107 {
108     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
109 
110     TRACE("iface %p, device %p.\n", iface, device);
111 
112     *device = texture->parent_device;
113     IDirect3DDevice8_AddRef(*device);
114 
115     TRACE("Returning device %p.\n", *device);
116 
117     return D3D_OK;
118 }
119 
120 static HRESULT WINAPI d3d8_texture_2d_SetPrivateData(IDirect3DTexture8 *iface,
121         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
122 {
123     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
124     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
125             iface, debugstr_guid(guid), data, data_size, flags);
126 
127     return d3d8_resource_set_private_data(&texture->resource, guid, data, data_size, flags);
128 }
129 
130 static HRESULT WINAPI d3d8_texture_2d_GetPrivateData(IDirect3DTexture8 *iface,
131         REFGUID guid, void *data, DWORD *data_size)
132 {
133     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
134     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
135             iface, debugstr_guid(guid), data, data_size);
136 
137     return d3d8_resource_get_private_data(&texture->resource, guid, data, data_size);
138 }
139 
140 static HRESULT WINAPI d3d8_texture_2d_FreePrivateData(IDirect3DTexture8 *iface, REFGUID guid)
141 {
142     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
143     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
144 
145     return d3d8_resource_free_private_data(&texture->resource, guid);
146 }
147 
148 static DWORD WINAPI d3d8_texture_2d_SetPriority(IDirect3DTexture8 *iface, DWORD priority)
149 {
150     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
151     struct wined3d_resource *resource;
152     DWORD ret;
153 
154     TRACE("iface %p, priority %u.\n", iface, priority);
155 
156     wined3d_mutex_lock();
157     resource = wined3d_texture_get_resource(texture->wined3d_texture);
158     ret = wined3d_resource_set_priority(resource, priority);
159     wined3d_mutex_unlock();
160 
161     return ret;
162 }
163 
164 static DWORD WINAPI d3d8_texture_2d_GetPriority(IDirect3DTexture8 *iface)
165 {
166     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
167     const struct wined3d_resource *resource;
168     DWORD ret;
169 
170     TRACE("iface %p.\n", iface);
171 
172     wined3d_mutex_lock();
173     resource = wined3d_texture_get_resource(texture->wined3d_texture);
174     ret = wined3d_resource_get_priority(resource);
175     wined3d_mutex_unlock();
176 
177     return ret;
178 }
179 
180 static void WINAPI d3d8_texture_2d_PreLoad(IDirect3DTexture8 *iface)
181 {
182     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
183 
184     TRACE("iface %p.\n", iface);
185 
186     wined3d_mutex_lock();
187     wined3d_texture_preload(texture->wined3d_texture);
188     wined3d_mutex_unlock();
189 }
190 
191 static D3DRESOURCETYPE WINAPI d3d8_texture_2d_GetType(IDirect3DTexture8 *iface)
192 {
193     TRACE("iface %p.\n", iface);
194 
195     return D3DRTYPE_TEXTURE;
196 }
197 
198 static DWORD WINAPI d3d8_texture_2d_SetLOD(IDirect3DTexture8 *iface, DWORD lod)
199 {
200     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
201     DWORD ret;
202 
203     TRACE("iface %p, lod %u.\n", iface, lod);
204 
205     wined3d_mutex_lock();
206     ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
207     wined3d_mutex_unlock();
208 
209     return ret;
210 }
211 
212 static DWORD WINAPI d3d8_texture_2d_GetLOD(IDirect3DTexture8 *iface)
213 {
214     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
215     DWORD ret;
216 
217     TRACE("iface %p.\n", iface);
218 
219     wined3d_mutex_lock();
220     ret = wined3d_texture_get_lod(texture->wined3d_texture);
221     wined3d_mutex_unlock();
222 
223     return ret;
224 }
225 
226 static DWORD WINAPI d3d8_texture_2d_GetLevelCount(IDirect3DTexture8 *iface)
227 {
228     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
229     DWORD ret;
230 
231     TRACE("iface %p.\n", iface);
232 
233     wined3d_mutex_lock();
234     ret = wined3d_texture_get_level_count(texture->wined3d_texture);
235     wined3d_mutex_unlock();
236 
237     return ret;
238 }
239 
240 static HRESULT WINAPI d3d8_texture_2d_GetLevelDesc(IDirect3DTexture8 *iface, UINT level, D3DSURFACE_DESC *desc)
241 {
242     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
243     struct wined3d_resource *sub_resource;
244     HRESULT hr = D3D_OK;
245 
246     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
247 
248     wined3d_mutex_lock();
249     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
250         hr = D3DERR_INVALIDCALL;
251     else
252     {
253         struct wined3d_resource_desc wined3d_desc;
254 
255         wined3d_resource_get_desc(sub_resource, &wined3d_desc);
256         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
257         desc->Type = wined3d_desc.resource_type;
258         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
259         desc->Pool = wined3d_desc.pool;
260         desc->Size = wined3d_desc.size;
261         desc->MultiSampleType = wined3d_desc.multisample_type;
262         desc->Width = wined3d_desc.width;
263         desc->Height = wined3d_desc.height;
264     }
265     wined3d_mutex_unlock();
266 
267     return hr;
268 }
269 
270 static HRESULT WINAPI d3d8_texture_2d_GetSurfaceLevel(IDirect3DTexture8 *iface,
271         UINT level, IDirect3DSurface8 **surface)
272 {
273     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
274     struct d3d8_surface *surface_impl;
275 
276     TRACE("iface %p, level %u, surface %p.\n", iface, level, surface);
277 
278     wined3d_mutex_lock();
279     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
280     {
281         wined3d_mutex_unlock();
282         return D3DERR_INVALIDCALL;
283     }
284 
285     *surface = &surface_impl->IDirect3DSurface8_iface;
286     IDirect3DSurface8_AddRef(*surface);
287     wined3d_mutex_unlock();
288 
289     return D3D_OK;
290 }
291 
292 static HRESULT WINAPI d3d8_texture_2d_LockRect(IDirect3DTexture8 *iface, UINT level,
293         D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
294 {
295     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
296     struct d3d8_surface *surface_impl;
297     HRESULT hr;
298 
299     TRACE("iface %p, level %u, locked_rect %p, rect %p, flags %#x.\n",
300             iface, level, locked_rect, rect, flags);
301 
302     wined3d_mutex_lock();
303     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
304         hr = D3DERR_INVALIDCALL;
305     else
306         hr = IDirect3DSurface8_LockRect(&surface_impl->IDirect3DSurface8_iface, locked_rect, rect, flags);
307     wined3d_mutex_unlock();
308 
309     return hr;
310 }
311 
312 static HRESULT WINAPI d3d8_texture_2d_UnlockRect(IDirect3DTexture8 *iface, UINT level)
313 {
314     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
315     struct d3d8_surface *surface_impl;
316     HRESULT hr;
317 
318     TRACE("iface %p, level %u.\n", iface, level);
319 
320     wined3d_mutex_lock();
321     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
322         hr = D3DERR_INVALIDCALL;
323     else
324         hr = IDirect3DSurface8_UnlockRect(&surface_impl->IDirect3DSurface8_iface);
325     wined3d_mutex_unlock();
326 
327     return hr;
328 }
329 
330 static HRESULT WINAPI d3d8_texture_2d_AddDirtyRect(IDirect3DTexture8 *iface, const RECT *dirty_rect)
331 {
332     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
333     HRESULT hr;
334 
335     TRACE("iface %p, dirty_rect %s.\n",
336             iface, wine_dbgstr_rect(dirty_rect));
337 
338     wined3d_mutex_lock();
339     if (!dirty_rect)
340         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, NULL);
341     else
342     {
343         struct wined3d_box dirty_region;
344 
345         dirty_region.left = dirty_rect->left;
346         dirty_region.top = dirty_rect->top;
347         dirty_region.right = dirty_rect->right;
348         dirty_region.bottom = dirty_rect->bottom;
349         dirty_region.front = 0;
350         dirty_region.back = 1;
351         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, &dirty_region);
352     }
353     wined3d_mutex_unlock();
354 
355     return hr;
356 }
357 
358 static const IDirect3DTexture8Vtbl Direct3DTexture8_Vtbl =
359 {
360     /* IUnknown */
361     d3d8_texture_2d_QueryInterface,
362     d3d8_texture_2d_AddRef,
363     d3d8_texture_2d_Release,
364     /* IDirect3DResource8 */
365     d3d8_texture_2d_GetDevice,
366     d3d8_texture_2d_SetPrivateData,
367     d3d8_texture_2d_GetPrivateData,
368     d3d8_texture_2d_FreePrivateData,
369     d3d8_texture_2d_SetPriority,
370     d3d8_texture_2d_GetPriority,
371     d3d8_texture_2d_PreLoad,
372     d3d8_texture_2d_GetType,
373     /* IDirect3dBaseTexture8 */
374     d3d8_texture_2d_SetLOD,
375     d3d8_texture_2d_GetLOD,
376     d3d8_texture_2d_GetLevelCount,
377     /* IDirect3DTexture8 */
378     d3d8_texture_2d_GetLevelDesc,
379     d3d8_texture_2d_GetSurfaceLevel,
380     d3d8_texture_2d_LockRect,
381     d3d8_texture_2d_UnlockRect,
382     d3d8_texture_2d_AddDirtyRect,
383 };
384 
385 static HRESULT WINAPI d3d8_texture_cube_QueryInterface(IDirect3DCubeTexture8 *iface, REFIID riid, void **out)
386 {
387     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
388 
389     if (IsEqualGUID(riid, &IID_IDirect3DCubeTexture8)
390             || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8)
391             || IsEqualGUID(riid, &IID_IDirect3DResource8)
392             || IsEqualGUID(riid, &IID_IUnknown))
393     {
394         IDirect3DCubeTexture8_AddRef(iface);
395         *out = iface;
396         return S_OK;
397     }
398 
399     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
400 
401     *out = NULL;
402     return E_NOINTERFACE;
403 }
404 
405 static ULONG WINAPI d3d8_texture_cube_AddRef(IDirect3DCubeTexture8 *iface)
406 {
407     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
408     ULONG ref = InterlockedIncrement(&texture->resource.refcount);
409 
410     TRACE("%p increasing refcount to %u.\n", iface, ref);
411 
412     if (ref == 1)
413     {
414         struct d3d8_surface *surface;
415 
416         IDirect3DDevice8_AddRef(texture->parent_device);
417         wined3d_mutex_lock();
418         LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
419         {
420             wined3d_rendertarget_view_incref(surface->wined3d_rtv);
421         }
422         wined3d_texture_incref(texture->wined3d_texture);
423         wined3d_mutex_unlock();
424     }
425 
426     return ref;
427 }
428 
429 static ULONG WINAPI d3d8_texture_cube_Release(IDirect3DCubeTexture8 *iface)
430 {
431     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
432     ULONG ref = InterlockedDecrement(&texture->resource.refcount);
433 
434     TRACE("%p decreasing refcount to %u.\n", iface, ref);
435 
436     if (!ref)
437     {
438         IDirect3DDevice8 *parent_device = texture->parent_device;
439         struct d3d8_surface *surface;
440 
441         TRACE("Releasing child %p.\n", texture->wined3d_texture);
442 
443         wined3d_mutex_lock();
444         LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
445         {
446             wined3d_rendertarget_view_decref(surface->wined3d_rtv);
447         }
448         wined3d_texture_decref(texture->wined3d_texture);
449         wined3d_mutex_unlock();
450 
451         /* Release the device last, as it may cause the device to be destroyed. */
452         IDirect3DDevice8_Release(parent_device);
453     }
454     return ref;
455 }
456 
457 static HRESULT WINAPI d3d8_texture_cube_GetDevice(IDirect3DCubeTexture8 *iface, IDirect3DDevice8 **device)
458 {
459     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
460 
461     TRACE("iface %p, device %p.\n", iface, device);
462 
463     *device = texture->parent_device;
464     IDirect3DDevice8_AddRef(*device);
465 
466     TRACE("Returning device %p.\n", *device);
467 
468     return D3D_OK;
469 }
470 
471 static HRESULT WINAPI d3d8_texture_cube_SetPrivateData(IDirect3DCubeTexture8 *iface,
472         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
473 {
474     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
475     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
476             iface, debugstr_guid(guid), data, data_size, flags);
477 
478     return d3d8_resource_set_private_data(&texture->resource, guid, data, data_size, flags);
479 }
480 
481 static HRESULT WINAPI d3d8_texture_cube_GetPrivateData(IDirect3DCubeTexture8 *iface,
482         REFGUID guid, void *data, DWORD *data_size)
483 {
484     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
485     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
486             iface, debugstr_guid(guid), data, data_size);
487 
488     return d3d8_resource_get_private_data(&texture->resource, guid, data, data_size);
489 }
490 
491 static HRESULT WINAPI d3d8_texture_cube_FreePrivateData(IDirect3DCubeTexture8 *iface, REFGUID guid)
492 {
493     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
494     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
495 
496     return d3d8_resource_free_private_data(&texture->resource, guid);
497 }
498 
499 static DWORD WINAPI d3d8_texture_cube_SetPriority(IDirect3DCubeTexture8 *iface, DWORD priority)
500 {
501     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
502     struct wined3d_resource *resource;
503     DWORD ret;
504 
505     TRACE("iface %p, priority %u.\n", iface, priority);
506 
507     wined3d_mutex_lock();
508     resource = wined3d_texture_get_resource(texture->wined3d_texture);
509     ret = wined3d_resource_set_priority(resource, priority);
510     wined3d_mutex_unlock();
511 
512     return ret;
513 }
514 
515 static DWORD WINAPI d3d8_texture_cube_GetPriority(IDirect3DCubeTexture8 *iface)
516 {
517     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
518     const struct wined3d_resource *resource;
519     DWORD ret;
520 
521     TRACE("iface %p.\n", iface);
522 
523     wined3d_mutex_lock();
524     resource = wined3d_texture_get_resource(texture->wined3d_texture);
525     ret =  wined3d_resource_get_priority(resource);
526     wined3d_mutex_unlock();
527 
528     return ret;
529 }
530 
531 static void WINAPI d3d8_texture_cube_PreLoad(IDirect3DCubeTexture8 *iface)
532 {
533     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
534 
535     TRACE("iface %p.\n", iface);
536 
537     wined3d_mutex_lock();
538     wined3d_texture_preload(texture->wined3d_texture);
539     wined3d_mutex_unlock();
540 }
541 
542 static D3DRESOURCETYPE WINAPI d3d8_texture_cube_GetType(IDirect3DCubeTexture8 *iface)
543 {
544     TRACE("iface %p.\n", iface);
545 
546     return D3DRTYPE_CUBETEXTURE;
547 }
548 
549 static DWORD WINAPI d3d8_texture_cube_SetLOD(IDirect3DCubeTexture8 *iface, DWORD lod)
550 {
551     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
552     DWORD ret;
553 
554     TRACE("iface %p, lod %u.\n", iface, lod);
555 
556     wined3d_mutex_lock();
557     ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
558     wined3d_mutex_unlock();
559 
560     return ret;
561 }
562 
563 static DWORD WINAPI d3d8_texture_cube_GetLOD(IDirect3DCubeTexture8 *iface)
564 {
565     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
566     DWORD ret;
567 
568     TRACE("iface %p.\n", iface);
569 
570     wined3d_mutex_lock();
571     ret = wined3d_texture_get_lod(texture->wined3d_texture);
572     wined3d_mutex_unlock();
573 
574     return ret;
575 }
576 
577 static DWORD WINAPI d3d8_texture_cube_GetLevelCount(IDirect3DCubeTexture8 *iface)
578 {
579     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
580     DWORD ret;
581 
582     TRACE("iface %p.\n", iface);
583 
584     wined3d_mutex_lock();
585     ret = wined3d_texture_get_level_count(texture->wined3d_texture);
586     wined3d_mutex_unlock();
587 
588     return ret;
589 }
590 
591 static HRESULT WINAPI d3d8_texture_cube_GetLevelDesc(IDirect3DCubeTexture8 *iface, UINT level, D3DSURFACE_DESC *desc)
592 {
593     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
594     struct wined3d_resource *sub_resource;
595     HRESULT hr = D3D_OK;
596 
597     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
598 
599     wined3d_mutex_lock();
600     if (level >= wined3d_texture_get_level_count(texture->wined3d_texture))
601     {
602         wined3d_mutex_unlock();
603         return D3DERR_INVALIDCALL;
604     }
605 
606     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
607         hr = D3DERR_INVALIDCALL;
608     else
609     {
610         struct wined3d_resource_desc wined3d_desc;
611 
612         wined3d_resource_get_desc(sub_resource, &wined3d_desc);
613         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
614         desc->Type = wined3d_desc.resource_type;
615         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
616         desc->Pool = wined3d_desc.pool;
617         desc->Size = wined3d_desc.size;
618         desc->MultiSampleType = wined3d_desc.multisample_type;
619         desc->Width = wined3d_desc.width;
620         desc->Height = wined3d_desc.height;
621     }
622     wined3d_mutex_unlock();
623 
624     return hr;
625 }
626 
627 static HRESULT WINAPI d3d8_texture_cube_GetCubeMapSurface(IDirect3DCubeTexture8 *iface,
628         D3DCUBEMAP_FACES face, UINT level, IDirect3DSurface8 **surface)
629 {
630     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
631     struct d3d8_surface *surface_impl;
632     UINT sub_resource_idx;
633     DWORD level_count;
634 
635     TRACE("iface %p, face %#x, level %u, surface %p.\n", iface, face, level, surface);
636 
637     wined3d_mutex_lock();
638     level_count = wined3d_texture_get_level_count(texture->wined3d_texture);
639     if (level >= level_count)
640     {
641         wined3d_mutex_unlock();
642         return D3DERR_INVALIDCALL;
643     }
644 
645     sub_resource_idx = level_count * face + level;
646     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx)))
647     {
648         wined3d_mutex_unlock();
649         return D3DERR_INVALIDCALL;
650     }
651 
652     *surface = &surface_impl->IDirect3DSurface8_iface;
653     IDirect3DSurface8_AddRef(*surface);
654     wined3d_mutex_unlock();
655 
656     return D3D_OK;
657 }
658 
659 static HRESULT WINAPI d3d8_texture_cube_LockRect(IDirect3DCubeTexture8 *iface,
660         D3DCUBEMAP_FACES face, UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect,
661         DWORD flags)
662 {
663     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
664     struct d3d8_surface *surface_impl;
665     UINT sub_resource_idx;
666     HRESULT hr;
667 
668     TRACE("iface %p, face %#x, level %u, locked_rect %p, rect %p, flags %#x.\n",
669             iface, face, level, locked_rect, rect, flags);
670 
671     wined3d_mutex_lock();
672     sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
673     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx)))
674         hr = D3DERR_INVALIDCALL;
675     else
676         hr = IDirect3DSurface8_LockRect(&surface_impl->IDirect3DSurface8_iface, locked_rect, rect, flags);
677     wined3d_mutex_unlock();
678 
679     return hr;
680 }
681 
682 static HRESULT WINAPI d3d8_texture_cube_UnlockRect(IDirect3DCubeTexture8 *iface,
683         D3DCUBEMAP_FACES face, UINT level)
684 {
685     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
686     struct d3d8_surface *surface_impl;
687     UINT sub_resource_idx;
688     HRESULT hr;
689 
690     TRACE("iface %p, face %#x, level %u.\n", iface, face, level);
691 
692     wined3d_mutex_lock();
693     sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
694     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx)))
695         hr = D3DERR_INVALIDCALL;
696     else
697         hr = IDirect3DSurface8_UnlockRect(&surface_impl->IDirect3DSurface8_iface);
698     wined3d_mutex_unlock();
699 
700     return hr;
701 }
702 
703 static HRESULT WINAPI d3d8_texture_cube_AddDirtyRect(IDirect3DCubeTexture8 *iface,
704         D3DCUBEMAP_FACES face, const RECT *dirty_rect)
705 {
706     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
707     HRESULT hr;
708 
709     TRACE("iface %p, face %#x, dirty_rect %s.\n",
710             iface, face, wine_dbgstr_rect(dirty_rect));
711 
712     wined3d_mutex_lock();
713     if (!dirty_rect)
714         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, NULL);
715     else
716     {
717         struct wined3d_box dirty_region;
718 
719         dirty_region.left = dirty_rect->left;
720         dirty_region.top = dirty_rect->top;
721         dirty_region.right = dirty_rect->right;
722         dirty_region.bottom = dirty_rect->bottom;
723         dirty_region.front = 0;
724         dirty_region.back = 1;
725         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, &dirty_region);
726     }
727     wined3d_mutex_unlock();
728 
729     return hr;
730 }
731 
732 static const IDirect3DCubeTexture8Vtbl Direct3DCubeTexture8_Vtbl =
733 {
734     /* IUnknown */
735     d3d8_texture_cube_QueryInterface,
736     d3d8_texture_cube_AddRef,
737     d3d8_texture_cube_Release,
738     /* IDirect3DResource8 */
739     d3d8_texture_cube_GetDevice,
740     d3d8_texture_cube_SetPrivateData,
741     d3d8_texture_cube_GetPrivateData,
742     d3d8_texture_cube_FreePrivateData,
743     d3d8_texture_cube_SetPriority,
744     d3d8_texture_cube_GetPriority,
745     d3d8_texture_cube_PreLoad,
746     d3d8_texture_cube_GetType,
747     /* IDirect3DBaseTexture8 */
748     d3d8_texture_cube_SetLOD,
749     d3d8_texture_cube_GetLOD,
750     d3d8_texture_cube_GetLevelCount,
751     /* IDirect3DCubeTexture8 */
752     d3d8_texture_cube_GetLevelDesc,
753     d3d8_texture_cube_GetCubeMapSurface,
754     d3d8_texture_cube_LockRect,
755     d3d8_texture_cube_UnlockRect,
756     d3d8_texture_cube_AddDirtyRect,
757 };
758 
759 static HRESULT WINAPI d3d8_texture_3d_QueryInterface(IDirect3DVolumeTexture8 *iface, REFIID riid, void **out)
760 {
761     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
762 
763     if (IsEqualGUID(riid, &IID_IDirect3DVolumeTexture8)
764             || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8)
765             || IsEqualGUID(riid, &IID_IDirect3DResource8)
766             || IsEqualGUID(riid, &IID_IUnknown))
767     {
768         IDirect3DVolumeTexture8_AddRef(iface);
769         *out = iface;
770         return S_OK;
771     }
772 
773     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
774 
775     *out = NULL;
776     return E_NOINTERFACE;
777 }
778 
779 static ULONG WINAPI d3d8_texture_3d_AddRef(IDirect3DVolumeTexture8 *iface)
780 {
781     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
782     ULONG ref = InterlockedIncrement(&texture->resource.refcount);
783 
784     TRACE("%p increasing refcount to %u.\n", iface, ref);
785 
786     if (ref == 1)
787     {
788         IDirect3DDevice8_AddRef(texture->parent_device);
789         wined3d_mutex_lock();
790         wined3d_texture_incref(texture->wined3d_texture);
791         wined3d_mutex_unlock();
792     }
793 
794     return ref;
795 }
796 
797 static ULONG WINAPI d3d8_texture_3d_Release(IDirect3DVolumeTexture8 *iface)
798 {
799     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
800     ULONG ref = InterlockedDecrement(&texture->resource.refcount);
801 
802     TRACE("%p decreasing refcount to %u.\n", iface, ref);
803 
804     if (!ref)
805     {
806         IDirect3DDevice8 *parent_device = texture->parent_device;
807 
808         wined3d_mutex_lock();
809         wined3d_texture_decref(texture->wined3d_texture);
810         wined3d_mutex_unlock();
811 
812         /* Release the device last, as it may cause the device to be destroyed. */
813         IDirect3DDevice8_Release(parent_device);
814     }
815     return ref;
816 }
817 
818 static HRESULT WINAPI d3d8_texture_3d_GetDevice(IDirect3DVolumeTexture8 *iface, IDirect3DDevice8 **device)
819 {
820     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
821 
822     TRACE("iface %p, device %p.\n", iface, device);
823 
824     *device = texture->parent_device;
825     IDirect3DDevice8_AddRef(*device);
826 
827     TRACE("Returning device %p.\n", *device);
828 
829     return D3D_OK;
830 }
831 
832 static HRESULT WINAPI d3d8_texture_3d_SetPrivateData(IDirect3DVolumeTexture8 *iface,
833         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
834 {
835     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
836     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
837             iface, debugstr_guid(guid), data, data_size, flags);
838 
839     return d3d8_resource_set_private_data(&texture->resource, guid, data, data_size, flags);
840 }
841 
842 static HRESULT WINAPI d3d8_texture_3d_GetPrivateData(IDirect3DVolumeTexture8 *iface,
843         REFGUID guid, void *data, DWORD *data_size)
844 {
845     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
846     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
847             iface, debugstr_guid(guid), data, data_size);
848 
849     return d3d8_resource_get_private_data(&texture->resource, guid, data, data_size);
850 }
851 
852 static HRESULT WINAPI d3d8_texture_3d_FreePrivateData(IDirect3DVolumeTexture8 *iface, REFGUID guid)
853 {
854     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
855     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
856 
857     return d3d8_resource_free_private_data(&texture->resource, guid);
858 }
859 
860 static DWORD WINAPI d3d8_texture_3d_SetPriority(IDirect3DVolumeTexture8 *iface, DWORD priority)
861 {
862     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
863     struct wined3d_resource *resource;
864     DWORD ret;
865 
866     TRACE("iface %p, priority %u.\n", iface, priority);
867 
868     wined3d_mutex_lock();
869     resource = wined3d_texture_get_resource(texture->wined3d_texture);
870     ret = wined3d_resource_set_priority(resource, priority);
871     wined3d_mutex_unlock();
872 
873     return ret;
874 }
875 
876 static DWORD WINAPI d3d8_texture_3d_GetPriority(IDirect3DVolumeTexture8 *iface)
877 {
878     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
879     const struct wined3d_resource *resource;
880     DWORD ret;
881 
882     TRACE("iface %p.\n", iface);
883 
884     wined3d_mutex_lock();
885     resource = wined3d_texture_get_resource(texture->wined3d_texture);
886     ret = wined3d_resource_get_priority(resource);
887     wined3d_mutex_unlock();
888 
889     return ret;
890 }
891 
892 static void WINAPI d3d8_texture_3d_PreLoad(IDirect3DVolumeTexture8 *iface)
893 {
894     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
895 
896     TRACE("iface %p.\n", iface);
897 
898     wined3d_mutex_lock();
899     wined3d_texture_preload(texture->wined3d_texture);
900     wined3d_mutex_unlock();
901 }
902 
903 static D3DRESOURCETYPE WINAPI d3d8_texture_3d_GetType(IDirect3DVolumeTexture8 *iface)
904 {
905     TRACE("iface %p.\n", iface);
906 
907     return D3DRTYPE_VOLUMETEXTURE;
908 }
909 
910 static DWORD WINAPI d3d8_texture_3d_SetLOD(IDirect3DVolumeTexture8 *iface, DWORD lod)
911 {
912     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
913     DWORD ret;
914 
915     TRACE("iface %p, lod %u.\n", iface, lod);
916 
917     wined3d_mutex_lock();
918     ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
919     wined3d_mutex_unlock();
920 
921     return ret;
922 }
923 
924 static DWORD WINAPI d3d8_texture_3d_GetLOD(IDirect3DVolumeTexture8 *iface)
925 {
926     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
927     DWORD ret;
928 
929     TRACE("iface %p.\n", iface);
930 
931     wined3d_mutex_lock();
932     ret = wined3d_texture_get_lod(texture->wined3d_texture);
933     wined3d_mutex_unlock();
934 
935     return ret;
936 }
937 
938 static DWORD WINAPI d3d8_texture_3d_GetLevelCount(IDirect3DVolumeTexture8 *iface)
939 {
940     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
941     DWORD ret;
942 
943     TRACE("iface %p.\n", iface);
944 
945     wined3d_mutex_lock();
946     ret = wined3d_texture_get_level_count(texture->wined3d_texture);
947     wined3d_mutex_unlock();
948 
949     return ret;
950 }
951 
952 static HRESULT WINAPI d3d8_texture_3d_GetLevelDesc(IDirect3DVolumeTexture8 *iface, UINT level, D3DVOLUME_DESC *desc)
953 {
954     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
955     struct wined3d_resource *sub_resource;
956     HRESULT hr = D3D_OK;
957 
958     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
959 
960     wined3d_mutex_lock();
961     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
962         hr = D3DERR_INVALIDCALL;
963     else
964     {
965         struct wined3d_resource_desc wined3d_desc;
966 
967         wined3d_resource_get_desc(sub_resource, &wined3d_desc);
968         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
969         desc->Type = wined3d_desc.resource_type;
970         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
971         desc->Pool = wined3d_desc.pool;
972         desc->Size = wined3d_desc.size;
973         desc->Width = wined3d_desc.width;
974         desc->Height = wined3d_desc.height;
975         desc->Depth = wined3d_desc.depth;
976     }
977     wined3d_mutex_unlock();
978 
979     return hr;
980 }
981 
982 static HRESULT WINAPI d3d8_texture_3d_GetVolumeLevel(IDirect3DVolumeTexture8 *iface,
983         UINT level, IDirect3DVolume8 **volume)
984 {
985     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
986     struct wined3d_resource *sub_resource;
987     struct d3d8_volume *volume_impl;
988 
989     TRACE("iface %p, level %u, volume %p.\n", iface, level, volume);
990 
991     wined3d_mutex_lock();
992     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
993     {
994         wined3d_mutex_unlock();
995         return D3DERR_INVALIDCALL;
996     }
997 
998     volume_impl = wined3d_resource_get_parent(sub_resource);
999     *volume = &volume_impl->IDirect3DVolume8_iface;
1000     IDirect3DVolume8_AddRef(*volume);
1001     wined3d_mutex_unlock();
1002 
1003     return D3D_OK;
1004 }
1005 
1006 static HRESULT WINAPI d3d8_texture_3d_LockBox(IDirect3DVolumeTexture8 *iface,
1007         UINT level, D3DLOCKED_BOX *locked_box, const D3DBOX *box, DWORD flags)
1008 {
1009     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
1010     struct d3d8_volume *volume_impl;
1011     HRESULT hr;
1012 
1013     TRACE("iface %p, level %u, locked_box %p, box %p, flags %#x.\n",
1014             iface, level, locked_box, box, flags);
1015 
1016     wined3d_mutex_lock();
1017     if (!(volume_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
1018         hr = D3DERR_INVALIDCALL;
1019     else
1020         hr = IDirect3DVolume8_LockBox(&volume_impl->IDirect3DVolume8_iface, locked_box, box, flags);
1021     wined3d_mutex_unlock();
1022 
1023     return hr;
1024 }
1025 
1026 static HRESULT WINAPI d3d8_texture_3d_UnlockBox(IDirect3DVolumeTexture8 *iface, UINT level)
1027 {
1028     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
1029     struct d3d8_volume *volume_impl;
1030     HRESULT hr;
1031 
1032     TRACE("iface %p, level %u.\n", iface, level);
1033 
1034     wined3d_mutex_lock();
1035     if (!(volume_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
1036         hr = D3DERR_INVALIDCALL;
1037     else
1038         hr = IDirect3DVolume8_UnlockBox(&volume_impl->IDirect3DVolume8_iface);
1039     wined3d_mutex_unlock();
1040 
1041     return hr;
1042 }
1043 
1044 static HRESULT WINAPI d3d8_texture_3d_AddDirtyBox(IDirect3DVolumeTexture8 *iface, const D3DBOX *dirty_box)
1045 {
1046     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
1047     HRESULT hr;
1048 
1049     TRACE("iface %p, dirty_box %p.\n", iface, dirty_box);
1050 
1051     wined3d_mutex_lock();
1052     hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, (const struct wined3d_box *)dirty_box);
1053     wined3d_mutex_unlock();
1054 
1055     return hr;
1056 }
1057 
1058 static const IDirect3DVolumeTexture8Vtbl Direct3DVolumeTexture8_Vtbl =
1059 {
1060     /* IUnknown */
1061     d3d8_texture_3d_QueryInterface,
1062     d3d8_texture_3d_AddRef,
1063     d3d8_texture_3d_Release,
1064     /* IDirect3DResource8 */
1065     d3d8_texture_3d_GetDevice,
1066     d3d8_texture_3d_SetPrivateData,
1067     d3d8_texture_3d_GetPrivateData,
1068     d3d8_texture_3d_FreePrivateData,
1069     d3d8_texture_3d_SetPriority,
1070     d3d8_texture_3d_GetPriority,
1071     d3d8_texture_3d_PreLoad,
1072     d3d8_texture_3d_GetType,
1073     /* IDirect3DBaseTexture8 */
1074     d3d8_texture_3d_SetLOD,
1075     d3d8_texture_3d_GetLOD,
1076     d3d8_texture_3d_GetLevelCount,
1077     /* IDirect3DVolumeTexture8 */
1078     d3d8_texture_3d_GetLevelDesc,
1079     d3d8_texture_3d_GetVolumeLevel,
1080     d3d8_texture_3d_LockBox,
1081     d3d8_texture_3d_UnlockBox,
1082     d3d8_texture_3d_AddDirtyBox
1083 };
1084 
1085 struct d3d8_texture *unsafe_impl_from_IDirect3DBaseTexture8(IDirect3DBaseTexture8 *iface)
1086 {
1087     if (!iface)
1088         return NULL;
1089 
1090     /* SetTexture() in particular doesn't do a lot of validation on the pointer
1091      * that gets passed in, and passing an invalid pointer works as long as the
1092      * application doesn't try to actually render anything with it, so we print
1093      * a WARN and return NULL instead of having the usual assert() here.
1094      * One application affected by this is Fishdom 2. */
1095     if (iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl
1096             && iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl
1097             && iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl)
1098     {
1099         WARN("%p is not a valid IDirect3DBaseTexture8 interface.\n", iface);
1100         return NULL;
1101     }
1102 
1103     return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
1104 }
1105 
1106 static void STDMETHODCALLTYPE d3d8_texture_wined3d_object_destroyed(void *parent)
1107 {
1108     struct d3d8_texture *texture = parent;
1109     d3d8_resource_cleanup(&texture->resource);
1110     HeapFree(GetProcessHeap(), 0, texture);
1111 }
1112 
1113 static const struct wined3d_parent_ops d3d8_texture_wined3d_parent_ops =
1114 {
1115     d3d8_texture_wined3d_object_destroyed,
1116 };
1117 
1118 HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
1119         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
1120 {
1121     struct wined3d_resource_desc desc;
1122     DWORD flags = 0;
1123     HRESULT hr;
1124 
1125     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl;
1126     d3d8_resource_init(&texture->resource);
1127     list_init(&texture->rtv_list);
1128 
1129     desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
1130     desc.format = wined3dformat_from_d3dformat(format);
1131     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
1132     desc.multisample_quality = 0;
1133     desc.usage = usage & WINED3DUSAGE_MASK;
1134     desc.usage |= WINED3DUSAGE_TEXTURE;
1135     desc.pool = pool;
1136     desc.width = width;
1137     desc.height = height;
1138     desc.depth = 1;
1139     desc.size = 0;
1140 
1141     if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
1142         flags |= WINED3D_TEXTURE_CREATE_MAPPABLE;
1143 
1144     if (!levels)
1145         levels = wined3d_log2i(max(width, height)) + 1;
1146 
1147     wined3d_mutex_lock();
1148     hr = wined3d_texture_create(device->wined3d_device, &desc, levels, flags,
1149             NULL, texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
1150     wined3d_mutex_unlock();
1151     if (FAILED(hr))
1152     {
1153         WARN("Failed to create wined3d texture, hr %#x.\n", hr);
1154         return hr;
1155     }
1156 
1157     texture->parent_device = &device->IDirect3DDevice8_iface;
1158     IDirect3DDevice8_AddRef(texture->parent_device);
1159 
1160     return D3D_OK;
1161 }
1162 
1163 HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
1164         UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
1165 {
1166     struct wined3d_resource_desc desc;
1167     DWORD flags = 0;
1168     HRESULT hr;
1169 
1170     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl;
1171     d3d8_resource_init(&texture->resource);
1172     list_init(&texture->rtv_list);
1173 
1174     desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
1175     desc.format = wined3dformat_from_d3dformat(format);
1176     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
1177     desc.multisample_quality = 0;
1178     desc.usage = usage & WINED3DUSAGE_MASK;
1179     desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP | WINED3DUSAGE_TEXTURE;
1180     desc.pool = pool;
1181     desc.width = edge_length;
1182     desc.height = edge_length;
1183     desc.depth = 1;
1184     desc.size = 0;
1185 
1186     if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
1187         flags |= WINED3D_TEXTURE_CREATE_MAPPABLE;
1188 
1189     if (!levels)
1190         levels = wined3d_log2i(edge_length) + 1;
1191 
1192     wined3d_mutex_lock();
1193     hr = wined3d_texture_create(device->wined3d_device, &desc, levels, flags,
1194             NULL, texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
1195     wined3d_mutex_unlock();
1196     if (FAILED(hr))
1197     {
1198         WARN("Failed to create wined3d cube texture, hr %#x.\n", hr);
1199         return hr;
1200     }
1201 
1202     texture->parent_device = &device->IDirect3DDevice8_iface;
1203     IDirect3DDevice8_AddRef(texture->parent_device);
1204 
1205     return D3D_OK;
1206 }
1207 
1208 HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
1209         UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
1210 {
1211     struct wined3d_resource_desc desc;
1212     HRESULT hr;
1213 
1214     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl;
1215     d3d8_resource_init(&texture->resource);
1216     list_init(&texture->rtv_list);
1217 
1218     desc.resource_type = WINED3D_RTYPE_TEXTURE_3D;
1219     desc.format = wined3dformat_from_d3dformat(format);
1220     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
1221     desc.multisample_quality = 0;
1222     desc.usage = usage & WINED3DUSAGE_MASK;
1223     desc.usage |= WINED3DUSAGE_TEXTURE;
1224     desc.pool = pool;
1225     desc.width = width;
1226     desc.height = height;
1227     desc.depth = depth;
1228     desc.size = 0;
1229 
1230     if (!levels)
1231         levels = wined3d_log2i(max(max(width, height), depth)) + 1;
1232 
1233     wined3d_mutex_lock();
1234     hr = wined3d_texture_create(device->wined3d_device, &desc, levels, 0,
1235             NULL, texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
1236     wined3d_mutex_unlock();
1237     if (FAILED(hr))
1238     {
1239         WARN("Failed to create wined3d volume texture, hr %#x.\n", hr);
1240         return hr;
1241     }
1242 
1243     texture->parent_device = &device->IDirect3DDevice8_iface;
1244     IDirect3DDevice8_AddRef(texture->parent_device);
1245 
1246     return D3D_OK;
1247 }
1248