xref: /reactos/dll/directx/wine/d3d8/texture.c (revision 84ccccab)
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((IDirect3DBaseTexture8 *)iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
24 }
25 
26 static inline struct d3d8_texture *impl_from_IDirect3DCubeTexture8(IDirect3DCubeTexture8 *iface)
27 {
28     return CONTAINING_RECORD((IDirect3DBaseTexture8 *)iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
29 }
30 
31 static inline struct d3d8_texture *impl_from_IDirect3DVolumeTexture8(IDirect3DVolumeTexture8 *iface)
32 {
33     return CONTAINING_RECORD((IDirect3DBaseTexture8 *)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_resource_preload(wined3d_texture_get_resource(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_sub_resource_desc wined3d_desc;
244     HRESULT hr;
245 
246     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
247 
248     wined3d_mutex_lock();
249     if (SUCCEEDED(hr = wined3d_texture_get_sub_resource_desc(texture->wined3d_texture, level, &wined3d_desc)))
250     {
251         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
252         desc->Type = D3DRTYPE_SURFACE;
253         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
254         desc->Pool = wined3d_desc.pool;
255         desc->Size = wined3d_desc.size;
256         desc->MultiSampleType = wined3d_desc.multisample_type;
257         desc->Width = wined3d_desc.width;
258         desc->Height = wined3d_desc.height;
259     }
260     wined3d_mutex_unlock();
261 
262     return hr;
263 }
264 
265 static HRESULT WINAPI d3d8_texture_2d_GetSurfaceLevel(IDirect3DTexture8 *iface,
266         UINT level, IDirect3DSurface8 **surface)
267 {
268     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
269     struct d3d8_surface *surface_impl;
270 
271     TRACE("iface %p, level %u, surface %p.\n", iface, level, surface);
272 
273     wined3d_mutex_lock();
274     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
275     {
276         wined3d_mutex_unlock();
277         return D3DERR_INVALIDCALL;
278     }
279 
280     *surface = &surface_impl->IDirect3DSurface8_iface;
281     IDirect3DSurface8_AddRef(*surface);
282     wined3d_mutex_unlock();
283 
284     return D3D_OK;
285 }
286 
287 static HRESULT WINAPI d3d8_texture_2d_LockRect(IDirect3DTexture8 *iface, UINT level,
288         D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
289 {
290     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
291     struct d3d8_surface *surface_impl;
292     HRESULT hr;
293 
294     TRACE("iface %p, level %u, locked_rect %p, rect %p, flags %#x.\n",
295             iface, level, locked_rect, rect, flags);
296 
297     wined3d_mutex_lock();
298     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
299         hr = D3DERR_INVALIDCALL;
300     else
301         hr = IDirect3DSurface8_LockRect(&surface_impl->IDirect3DSurface8_iface, locked_rect, rect, flags);
302     wined3d_mutex_unlock();
303 
304     return hr;
305 }
306 
307 static HRESULT WINAPI d3d8_texture_2d_UnlockRect(IDirect3DTexture8 *iface, UINT level)
308 {
309     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
310     struct d3d8_surface *surface_impl;
311     HRESULT hr;
312 
313     TRACE("iface %p, level %u.\n", iface, level);
314 
315     wined3d_mutex_lock();
316     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
317         hr = D3DERR_INVALIDCALL;
318     else
319         hr = IDirect3DSurface8_UnlockRect(&surface_impl->IDirect3DSurface8_iface);
320     wined3d_mutex_unlock();
321 
322     return hr;
323 }
324 
325 static HRESULT WINAPI d3d8_texture_2d_AddDirtyRect(IDirect3DTexture8 *iface, const RECT *dirty_rect)
326 {
327     struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface);
328     HRESULT hr;
329 
330     TRACE("iface %p, dirty_rect %s.\n",
331             iface, wine_dbgstr_rect(dirty_rect));
332 
333     wined3d_mutex_lock();
334     if (!dirty_rect)
335         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, NULL);
336     else
337     {
338         struct wined3d_box dirty_region;
339 
340         wined3d_box_set(&dirty_region, dirty_rect->left, dirty_rect->top, dirty_rect->right, dirty_rect->bottom, 0, 1);
341         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, &dirty_region);
342     }
343     wined3d_mutex_unlock();
344 
345     return hr;
346 }
347 
348 static const IDirect3DTexture8Vtbl Direct3DTexture8_Vtbl =
349 {
350     /* IUnknown */
351     d3d8_texture_2d_QueryInterface,
352     d3d8_texture_2d_AddRef,
353     d3d8_texture_2d_Release,
354     /* IDirect3DResource8 */
355     d3d8_texture_2d_GetDevice,
356     d3d8_texture_2d_SetPrivateData,
357     d3d8_texture_2d_GetPrivateData,
358     d3d8_texture_2d_FreePrivateData,
359     d3d8_texture_2d_SetPriority,
360     d3d8_texture_2d_GetPriority,
361     d3d8_texture_2d_PreLoad,
362     d3d8_texture_2d_GetType,
363     /* IDirect3dBaseTexture8 */
364     d3d8_texture_2d_SetLOD,
365     d3d8_texture_2d_GetLOD,
366     d3d8_texture_2d_GetLevelCount,
367     /* IDirect3DTexture8 */
368     d3d8_texture_2d_GetLevelDesc,
369     d3d8_texture_2d_GetSurfaceLevel,
370     d3d8_texture_2d_LockRect,
371     d3d8_texture_2d_UnlockRect,
372     d3d8_texture_2d_AddDirtyRect,
373 };
374 
375 static HRESULT WINAPI d3d8_texture_cube_QueryInterface(IDirect3DCubeTexture8 *iface, REFIID riid, void **out)
376 {
377     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
378 
379     if (IsEqualGUID(riid, &IID_IDirect3DCubeTexture8)
380             || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8)
381             || IsEqualGUID(riid, &IID_IDirect3DResource8)
382             || IsEqualGUID(riid, &IID_IUnknown))
383     {
384         IDirect3DCubeTexture8_AddRef(iface);
385         *out = iface;
386         return S_OK;
387     }
388 
389     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
390 
391     *out = NULL;
392     return E_NOINTERFACE;
393 }
394 
395 static ULONG WINAPI d3d8_texture_cube_AddRef(IDirect3DCubeTexture8 *iface)
396 {
397     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
398     ULONG ref = InterlockedIncrement(&texture->resource.refcount);
399 
400     TRACE("%p increasing refcount to %u.\n", iface, ref);
401 
402     if (ref == 1)
403     {
404         struct d3d8_surface *surface;
405 
406         IDirect3DDevice8_AddRef(texture->parent_device);
407         wined3d_mutex_lock();
408         LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
409         {
410             wined3d_rendertarget_view_incref(surface->wined3d_rtv);
411         }
412         wined3d_texture_incref(texture->wined3d_texture);
413         wined3d_mutex_unlock();
414     }
415 
416     return ref;
417 }
418 
419 static ULONG WINAPI d3d8_texture_cube_Release(IDirect3DCubeTexture8 *iface)
420 {
421     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
422     ULONG ref = InterlockedDecrement(&texture->resource.refcount);
423 
424     TRACE("%p decreasing refcount to %u.\n", iface, ref);
425 
426     if (!ref)
427     {
428         IDirect3DDevice8 *parent_device = texture->parent_device;
429         struct d3d8_surface *surface;
430 
431         TRACE("Releasing child %p.\n", texture->wined3d_texture);
432 
433         wined3d_mutex_lock();
434         LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d8_surface, rtv_entry)
435         {
436             wined3d_rendertarget_view_decref(surface->wined3d_rtv);
437         }
438         wined3d_texture_decref(texture->wined3d_texture);
439         wined3d_mutex_unlock();
440 
441         /* Release the device last, as it may cause the device to be destroyed. */
442         IDirect3DDevice8_Release(parent_device);
443     }
444     return ref;
445 }
446 
447 static HRESULT WINAPI d3d8_texture_cube_GetDevice(IDirect3DCubeTexture8 *iface, IDirect3DDevice8 **device)
448 {
449     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
450 
451     TRACE("iface %p, device %p.\n", iface, device);
452 
453     *device = texture->parent_device;
454     IDirect3DDevice8_AddRef(*device);
455 
456     TRACE("Returning device %p.\n", *device);
457 
458     return D3D_OK;
459 }
460 
461 static HRESULT WINAPI d3d8_texture_cube_SetPrivateData(IDirect3DCubeTexture8 *iface,
462         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
463 {
464     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
465     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
466             iface, debugstr_guid(guid), data, data_size, flags);
467 
468     return d3d8_resource_set_private_data(&texture->resource, guid, data, data_size, flags);
469 }
470 
471 static HRESULT WINAPI d3d8_texture_cube_GetPrivateData(IDirect3DCubeTexture8 *iface,
472         REFGUID guid, void *data, DWORD *data_size)
473 {
474     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
475     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
476             iface, debugstr_guid(guid), data, data_size);
477 
478     return d3d8_resource_get_private_data(&texture->resource, guid, data, data_size);
479 }
480 
481 static HRESULT WINAPI d3d8_texture_cube_FreePrivateData(IDirect3DCubeTexture8 *iface, REFGUID guid)
482 {
483     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
484     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
485 
486     return d3d8_resource_free_private_data(&texture->resource, guid);
487 }
488 
489 static DWORD WINAPI d3d8_texture_cube_SetPriority(IDirect3DCubeTexture8 *iface, DWORD priority)
490 {
491     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
492     struct wined3d_resource *resource;
493     DWORD ret;
494 
495     TRACE("iface %p, priority %u.\n", iface, priority);
496 
497     wined3d_mutex_lock();
498     resource = wined3d_texture_get_resource(texture->wined3d_texture);
499     ret = wined3d_resource_set_priority(resource, priority);
500     wined3d_mutex_unlock();
501 
502     return ret;
503 }
504 
505 static DWORD WINAPI d3d8_texture_cube_GetPriority(IDirect3DCubeTexture8 *iface)
506 {
507     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
508     const struct wined3d_resource *resource;
509     DWORD ret;
510 
511     TRACE("iface %p.\n", iface);
512 
513     wined3d_mutex_lock();
514     resource = wined3d_texture_get_resource(texture->wined3d_texture);
515     ret =  wined3d_resource_get_priority(resource);
516     wined3d_mutex_unlock();
517 
518     return ret;
519 }
520 
521 static void WINAPI d3d8_texture_cube_PreLoad(IDirect3DCubeTexture8 *iface)
522 {
523     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
524 
525     TRACE("iface %p.\n", iface);
526 
527     wined3d_mutex_lock();
528     wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture));
529     wined3d_mutex_unlock();
530 }
531 
532 static D3DRESOURCETYPE WINAPI d3d8_texture_cube_GetType(IDirect3DCubeTexture8 *iface)
533 {
534     TRACE("iface %p.\n", iface);
535 
536     return D3DRTYPE_CUBETEXTURE;
537 }
538 
539 static DWORD WINAPI d3d8_texture_cube_SetLOD(IDirect3DCubeTexture8 *iface, DWORD lod)
540 {
541     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
542     DWORD ret;
543 
544     TRACE("iface %p, lod %u.\n", iface, lod);
545 
546     wined3d_mutex_lock();
547     ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
548     wined3d_mutex_unlock();
549 
550     return ret;
551 }
552 
553 static DWORD WINAPI d3d8_texture_cube_GetLOD(IDirect3DCubeTexture8 *iface)
554 {
555     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
556     DWORD ret;
557 
558     TRACE("iface %p.\n", iface);
559 
560     wined3d_mutex_lock();
561     ret = wined3d_texture_get_lod(texture->wined3d_texture);
562     wined3d_mutex_unlock();
563 
564     return ret;
565 }
566 
567 static DWORD WINAPI d3d8_texture_cube_GetLevelCount(IDirect3DCubeTexture8 *iface)
568 {
569     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
570     DWORD ret;
571 
572     TRACE("iface %p.\n", iface);
573 
574     wined3d_mutex_lock();
575     ret = wined3d_texture_get_level_count(texture->wined3d_texture);
576     wined3d_mutex_unlock();
577 
578     return ret;
579 }
580 
581 static HRESULT WINAPI d3d8_texture_cube_GetLevelDesc(IDirect3DCubeTexture8 *iface, UINT level, D3DSURFACE_DESC *desc)
582 {
583     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
584     struct wined3d_sub_resource_desc wined3d_desc;
585     HRESULT hr;
586 
587     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
588 
589     wined3d_mutex_lock();
590     if (level >= wined3d_texture_get_level_count(texture->wined3d_texture))
591     {
592         wined3d_mutex_unlock();
593         return D3DERR_INVALIDCALL;
594     }
595 
596     if (SUCCEEDED(hr = wined3d_texture_get_sub_resource_desc(texture->wined3d_texture, level, &wined3d_desc)))
597     {
598         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
599         desc->Type = D3DRTYPE_SURFACE;
600         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
601         desc->Pool = wined3d_desc.pool;
602         desc->Size = wined3d_desc.size;
603         desc->MultiSampleType = wined3d_desc.multisample_type;
604         desc->Width = wined3d_desc.width;
605         desc->Height = wined3d_desc.height;
606     }
607     wined3d_mutex_unlock();
608 
609     return hr;
610 }
611 
612 static HRESULT WINAPI d3d8_texture_cube_GetCubeMapSurface(IDirect3DCubeTexture8 *iface,
613         D3DCUBEMAP_FACES face, UINT level, IDirect3DSurface8 **surface)
614 {
615     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
616     struct d3d8_surface *surface_impl;
617     UINT sub_resource_idx;
618     DWORD level_count;
619 
620     TRACE("iface %p, face %#x, level %u, surface %p.\n", iface, face, level, surface);
621 
622     wined3d_mutex_lock();
623     level_count = wined3d_texture_get_level_count(texture->wined3d_texture);
624     if (level >= level_count)
625     {
626         wined3d_mutex_unlock();
627         return D3DERR_INVALIDCALL;
628     }
629 
630     sub_resource_idx = level_count * face + level;
631     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx)))
632     {
633         wined3d_mutex_unlock();
634         return D3DERR_INVALIDCALL;
635     }
636 
637     *surface = &surface_impl->IDirect3DSurface8_iface;
638     IDirect3DSurface8_AddRef(*surface);
639     wined3d_mutex_unlock();
640 
641     return D3D_OK;
642 }
643 
644 static HRESULT WINAPI d3d8_texture_cube_LockRect(IDirect3DCubeTexture8 *iface,
645         D3DCUBEMAP_FACES face, UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect,
646         DWORD flags)
647 {
648     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
649     struct d3d8_surface *surface_impl;
650     UINT sub_resource_idx;
651     HRESULT hr;
652 
653     TRACE("iface %p, face %#x, level %u, locked_rect %p, rect %p, flags %#x.\n",
654             iface, face, level, locked_rect, rect, flags);
655 
656     wined3d_mutex_lock();
657     sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
658     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx)))
659         hr = D3DERR_INVALIDCALL;
660     else
661         hr = IDirect3DSurface8_LockRect(&surface_impl->IDirect3DSurface8_iface, locked_rect, rect, flags);
662     wined3d_mutex_unlock();
663 
664     return hr;
665 }
666 
667 static HRESULT WINAPI d3d8_texture_cube_UnlockRect(IDirect3DCubeTexture8 *iface,
668         D3DCUBEMAP_FACES face, UINT level)
669 {
670     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
671     struct d3d8_surface *surface_impl;
672     UINT sub_resource_idx;
673     HRESULT hr;
674 
675     TRACE("iface %p, face %#x, level %u.\n", iface, face, level);
676 
677     wined3d_mutex_lock();
678     sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
679     if (!(surface_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, sub_resource_idx)))
680         hr = D3DERR_INVALIDCALL;
681     else
682         hr = IDirect3DSurface8_UnlockRect(&surface_impl->IDirect3DSurface8_iface);
683     wined3d_mutex_unlock();
684 
685     return hr;
686 }
687 
688 static HRESULT WINAPI d3d8_texture_cube_AddDirtyRect(IDirect3DCubeTexture8 *iface,
689         D3DCUBEMAP_FACES face, const RECT *dirty_rect)
690 {
691     struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface);
692     HRESULT hr;
693 
694     TRACE("iface %p, face %#x, dirty_rect %s.\n",
695             iface, face, wine_dbgstr_rect(dirty_rect));
696 
697     wined3d_mutex_lock();
698     if (!dirty_rect)
699         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, NULL);
700     else
701     {
702         struct wined3d_box dirty_region;
703 
704         wined3d_box_set(&dirty_region, dirty_rect->left, dirty_rect->top, dirty_rect->right, dirty_rect->bottom, 0, 1);
705         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, &dirty_region);
706     }
707     wined3d_mutex_unlock();
708 
709     return hr;
710 }
711 
712 static const IDirect3DCubeTexture8Vtbl Direct3DCubeTexture8_Vtbl =
713 {
714     /* IUnknown */
715     d3d8_texture_cube_QueryInterface,
716     d3d8_texture_cube_AddRef,
717     d3d8_texture_cube_Release,
718     /* IDirect3DResource8 */
719     d3d8_texture_cube_GetDevice,
720     d3d8_texture_cube_SetPrivateData,
721     d3d8_texture_cube_GetPrivateData,
722     d3d8_texture_cube_FreePrivateData,
723     d3d8_texture_cube_SetPriority,
724     d3d8_texture_cube_GetPriority,
725     d3d8_texture_cube_PreLoad,
726     d3d8_texture_cube_GetType,
727     /* IDirect3DBaseTexture8 */
728     d3d8_texture_cube_SetLOD,
729     d3d8_texture_cube_GetLOD,
730     d3d8_texture_cube_GetLevelCount,
731     /* IDirect3DCubeTexture8 */
732     d3d8_texture_cube_GetLevelDesc,
733     d3d8_texture_cube_GetCubeMapSurface,
734     d3d8_texture_cube_LockRect,
735     d3d8_texture_cube_UnlockRect,
736     d3d8_texture_cube_AddDirtyRect,
737 };
738 
739 static HRESULT WINAPI d3d8_texture_3d_QueryInterface(IDirect3DVolumeTexture8 *iface, REFIID riid, void **out)
740 {
741     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
742 
743     if (IsEqualGUID(riid, &IID_IDirect3DVolumeTexture8)
744             || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8)
745             || IsEqualGUID(riid, &IID_IDirect3DResource8)
746             || IsEqualGUID(riid, &IID_IUnknown))
747     {
748         IDirect3DVolumeTexture8_AddRef(iface);
749         *out = iface;
750         return S_OK;
751     }
752 
753     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
754 
755     *out = NULL;
756     return E_NOINTERFACE;
757 }
758 
759 static ULONG WINAPI d3d8_texture_3d_AddRef(IDirect3DVolumeTexture8 *iface)
760 {
761     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
762     ULONG ref = InterlockedIncrement(&texture->resource.refcount);
763 
764     TRACE("%p increasing refcount to %u.\n", iface, ref);
765 
766     if (ref == 1)
767     {
768         IDirect3DDevice8_AddRef(texture->parent_device);
769         wined3d_mutex_lock();
770         wined3d_texture_incref(texture->wined3d_texture);
771         wined3d_mutex_unlock();
772     }
773 
774     return ref;
775 }
776 
777 static ULONG WINAPI d3d8_texture_3d_Release(IDirect3DVolumeTexture8 *iface)
778 {
779     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
780     ULONG ref = InterlockedDecrement(&texture->resource.refcount);
781 
782     TRACE("%p decreasing refcount to %u.\n", iface, ref);
783 
784     if (!ref)
785     {
786         IDirect3DDevice8 *parent_device = texture->parent_device;
787 
788         wined3d_mutex_lock();
789         wined3d_texture_decref(texture->wined3d_texture);
790         wined3d_mutex_unlock();
791 
792         /* Release the device last, as it may cause the device to be destroyed. */
793         IDirect3DDevice8_Release(parent_device);
794     }
795     return ref;
796 }
797 
798 static HRESULT WINAPI d3d8_texture_3d_GetDevice(IDirect3DVolumeTexture8 *iface, IDirect3DDevice8 **device)
799 {
800     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
801 
802     TRACE("iface %p, device %p.\n", iface, device);
803 
804     *device = texture->parent_device;
805     IDirect3DDevice8_AddRef(*device);
806 
807     TRACE("Returning device %p.\n", *device);
808 
809     return D3D_OK;
810 }
811 
812 static HRESULT WINAPI d3d8_texture_3d_SetPrivateData(IDirect3DVolumeTexture8 *iface,
813         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
814 {
815     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
816     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
817             iface, debugstr_guid(guid), data, data_size, flags);
818 
819     return d3d8_resource_set_private_data(&texture->resource, guid, data, data_size, flags);
820 }
821 
822 static HRESULT WINAPI d3d8_texture_3d_GetPrivateData(IDirect3DVolumeTexture8 *iface,
823         REFGUID guid, void *data, DWORD *data_size)
824 {
825     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
826     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
827             iface, debugstr_guid(guid), data, data_size);
828 
829     return d3d8_resource_get_private_data(&texture->resource, guid, data, data_size);
830 }
831 
832 static HRESULT WINAPI d3d8_texture_3d_FreePrivateData(IDirect3DVolumeTexture8 *iface, REFGUID guid)
833 {
834     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
835     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
836 
837     return d3d8_resource_free_private_data(&texture->resource, guid);
838 }
839 
840 static DWORD WINAPI d3d8_texture_3d_SetPriority(IDirect3DVolumeTexture8 *iface, DWORD priority)
841 {
842     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
843     struct wined3d_resource *resource;
844     DWORD ret;
845 
846     TRACE("iface %p, priority %u.\n", iface, priority);
847 
848     wined3d_mutex_lock();
849     resource = wined3d_texture_get_resource(texture->wined3d_texture);
850     ret = wined3d_resource_set_priority(resource, priority);
851     wined3d_mutex_unlock();
852 
853     return ret;
854 }
855 
856 static DWORD WINAPI d3d8_texture_3d_GetPriority(IDirect3DVolumeTexture8 *iface)
857 {
858     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
859     const struct wined3d_resource *resource;
860     DWORD ret;
861 
862     TRACE("iface %p.\n", iface);
863 
864     wined3d_mutex_lock();
865     resource = wined3d_texture_get_resource(texture->wined3d_texture);
866     ret = wined3d_resource_get_priority(resource);
867     wined3d_mutex_unlock();
868 
869     return ret;
870 }
871 
872 static void WINAPI d3d8_texture_3d_PreLoad(IDirect3DVolumeTexture8 *iface)
873 {
874     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
875 
876     TRACE("iface %p.\n", iface);
877 
878     wined3d_mutex_lock();
879     wined3d_resource_preload(wined3d_texture_get_resource(texture->wined3d_texture));
880     wined3d_mutex_unlock();
881 }
882 
883 static D3DRESOURCETYPE WINAPI d3d8_texture_3d_GetType(IDirect3DVolumeTexture8 *iface)
884 {
885     TRACE("iface %p.\n", iface);
886 
887     return D3DRTYPE_VOLUMETEXTURE;
888 }
889 
890 static DWORD WINAPI d3d8_texture_3d_SetLOD(IDirect3DVolumeTexture8 *iface, DWORD lod)
891 {
892     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
893     DWORD ret;
894 
895     TRACE("iface %p, lod %u.\n", iface, lod);
896 
897     wined3d_mutex_lock();
898     ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
899     wined3d_mutex_unlock();
900 
901     return ret;
902 }
903 
904 static DWORD WINAPI d3d8_texture_3d_GetLOD(IDirect3DVolumeTexture8 *iface)
905 {
906     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
907     DWORD ret;
908 
909     TRACE("iface %p.\n", iface);
910 
911     wined3d_mutex_lock();
912     ret = wined3d_texture_get_lod(texture->wined3d_texture);
913     wined3d_mutex_unlock();
914 
915     return ret;
916 }
917 
918 static DWORD WINAPI d3d8_texture_3d_GetLevelCount(IDirect3DVolumeTexture8 *iface)
919 {
920     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
921     DWORD ret;
922 
923     TRACE("iface %p.\n", iface);
924 
925     wined3d_mutex_lock();
926     ret = wined3d_texture_get_level_count(texture->wined3d_texture);
927     wined3d_mutex_unlock();
928 
929     return ret;
930 }
931 
932 static HRESULT WINAPI d3d8_texture_3d_GetLevelDesc(IDirect3DVolumeTexture8 *iface, UINT level, D3DVOLUME_DESC *desc)
933 {
934     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
935     struct wined3d_sub_resource_desc wined3d_desc;
936     HRESULT hr;
937 
938     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
939 
940     wined3d_mutex_lock();
941     if (SUCCEEDED(hr = wined3d_texture_get_sub_resource_desc(texture->wined3d_texture, level, &wined3d_desc)))
942     {
943         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
944         desc->Type = D3DRTYPE_VOLUME;
945         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
946         desc->Pool = wined3d_desc.pool;
947         desc->Size = wined3d_desc.size;
948         desc->Width = wined3d_desc.width;
949         desc->Height = wined3d_desc.height;
950         desc->Depth = wined3d_desc.depth;
951     }
952     wined3d_mutex_unlock();
953 
954     return hr;
955 }
956 
957 static HRESULT WINAPI d3d8_texture_3d_GetVolumeLevel(IDirect3DVolumeTexture8 *iface,
958         UINT level, IDirect3DVolume8 **volume)
959 {
960     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
961     struct d3d8_volume *volume_impl;
962 
963     TRACE("iface %p, level %u, volume %p.\n", iface, level, volume);
964 
965     wined3d_mutex_lock();
966     if (!(volume_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
967     {
968         wined3d_mutex_unlock();
969         return D3DERR_INVALIDCALL;
970     }
971 
972     *volume = &volume_impl->IDirect3DVolume8_iface;
973     IDirect3DVolume8_AddRef(*volume);
974     wined3d_mutex_unlock();
975 
976     return D3D_OK;
977 }
978 
979 static HRESULT WINAPI d3d8_texture_3d_LockBox(IDirect3DVolumeTexture8 *iface,
980         UINT level, D3DLOCKED_BOX *locked_box, const D3DBOX *box, DWORD flags)
981 {
982     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
983     struct d3d8_volume *volume_impl;
984     HRESULT hr;
985 
986     TRACE("iface %p, level %u, locked_box %p, box %p, flags %#x.\n",
987             iface, level, locked_box, box, flags);
988 
989     wined3d_mutex_lock();
990     if (!(volume_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
991         hr = D3DERR_INVALIDCALL;
992     else
993         hr = IDirect3DVolume8_LockBox(&volume_impl->IDirect3DVolume8_iface, locked_box, box, flags);
994     wined3d_mutex_unlock();
995 
996     return hr;
997 }
998 
999 static HRESULT WINAPI d3d8_texture_3d_UnlockBox(IDirect3DVolumeTexture8 *iface, UINT level)
1000 {
1001     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
1002     struct d3d8_volume *volume_impl;
1003     HRESULT hr;
1004 
1005     TRACE("iface %p, level %u.\n", iface, level);
1006 
1007     wined3d_mutex_lock();
1008     if (!(volume_impl = wined3d_texture_get_sub_resource_parent(texture->wined3d_texture, level)))
1009         hr = D3DERR_INVALIDCALL;
1010     else
1011         hr = IDirect3DVolume8_UnlockBox(&volume_impl->IDirect3DVolume8_iface);
1012     wined3d_mutex_unlock();
1013 
1014     return hr;
1015 }
1016 
1017 static HRESULT WINAPI d3d8_texture_3d_AddDirtyBox(IDirect3DVolumeTexture8 *iface, const D3DBOX *dirty_box)
1018 {
1019     struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface);
1020     HRESULT hr;
1021 
1022     TRACE("iface %p, dirty_box %p.\n", iface, dirty_box);
1023 
1024     wined3d_mutex_lock();
1025     hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, (const struct wined3d_box *)dirty_box);
1026     wined3d_mutex_unlock();
1027 
1028     return hr;
1029 }
1030 
1031 static const IDirect3DVolumeTexture8Vtbl Direct3DVolumeTexture8_Vtbl =
1032 {
1033     /* IUnknown */
1034     d3d8_texture_3d_QueryInterface,
1035     d3d8_texture_3d_AddRef,
1036     d3d8_texture_3d_Release,
1037     /* IDirect3DResource8 */
1038     d3d8_texture_3d_GetDevice,
1039     d3d8_texture_3d_SetPrivateData,
1040     d3d8_texture_3d_GetPrivateData,
1041     d3d8_texture_3d_FreePrivateData,
1042     d3d8_texture_3d_SetPriority,
1043     d3d8_texture_3d_GetPriority,
1044     d3d8_texture_3d_PreLoad,
1045     d3d8_texture_3d_GetType,
1046     /* IDirect3DBaseTexture8 */
1047     d3d8_texture_3d_SetLOD,
1048     d3d8_texture_3d_GetLOD,
1049     d3d8_texture_3d_GetLevelCount,
1050     /* IDirect3DVolumeTexture8 */
1051     d3d8_texture_3d_GetLevelDesc,
1052     d3d8_texture_3d_GetVolumeLevel,
1053     d3d8_texture_3d_LockBox,
1054     d3d8_texture_3d_UnlockBox,
1055     d3d8_texture_3d_AddDirtyBox
1056 };
1057 
1058 struct d3d8_texture *unsafe_impl_from_IDirect3DBaseTexture8(IDirect3DBaseTexture8 *iface)
1059 {
1060     if (!iface)
1061         return NULL;
1062 
1063     /* SetTexture() in particular doesn't do a lot of validation on the pointer
1064      * that gets passed in, and passing an invalid pointer works as long as the
1065      * application doesn't try to actually render anything with it, so we print
1066      * a WARN and return NULL instead of having the usual assert() here.
1067      * One application affected by this is Fishdom 2. */
1068     if (iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl
1069             && iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl
1070             && iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl)
1071     {
1072         WARN("%p is not a valid IDirect3DBaseTexture8 interface.\n", iface);
1073         return NULL;
1074     }
1075 
1076     return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface);
1077 }
1078 
1079 static void STDMETHODCALLTYPE d3d8_texture_wined3d_object_destroyed(void *parent)
1080 {
1081     struct d3d8_texture *texture = parent;
1082     d3d8_resource_cleanup(&texture->resource);
1083     HeapFree(GetProcessHeap(), 0, texture);
1084 }
1085 
1086 static const struct wined3d_parent_ops d3d8_texture_wined3d_parent_ops =
1087 {
1088     d3d8_texture_wined3d_object_destroyed,
1089 };
1090 
1091 HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
1092         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
1093 {
1094     struct wined3d_resource_desc desc;
1095     DWORD flags = 0;
1096     HRESULT hr;
1097 
1098     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl;
1099     d3d8_resource_init(&texture->resource);
1100     list_init(&texture->rtv_list);
1101 
1102     desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
1103     desc.format = wined3dformat_from_d3dformat(format);
1104     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
1105     desc.multisample_quality = 0;
1106     desc.usage = usage & WINED3DUSAGE_MASK;
1107     desc.usage |= WINED3DUSAGE_TEXTURE;
1108     desc.pool = pool;
1109     desc.width = width;
1110     desc.height = height;
1111     desc.depth = 1;
1112     desc.size = 0;
1113 
1114     if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
1115         flags |= WINED3D_TEXTURE_CREATE_MAPPABLE;
1116 
1117     if (!levels)
1118         levels = wined3d_log2i(max(width, height)) + 1;
1119 
1120     wined3d_mutex_lock();
1121     hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, flags,
1122             NULL, texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
1123     wined3d_mutex_unlock();
1124     if (FAILED(hr))
1125     {
1126         WARN("Failed to create wined3d texture, hr %#x.\n", hr);
1127         return hr;
1128     }
1129 
1130     texture->parent_device = &device->IDirect3DDevice8_iface;
1131     IDirect3DDevice8_AddRef(texture->parent_device);
1132 
1133     return D3D_OK;
1134 }
1135 
1136 HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
1137         UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
1138 {
1139     struct wined3d_resource_desc desc;
1140     DWORD flags = 0;
1141     HRESULT hr;
1142 
1143     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl;
1144     d3d8_resource_init(&texture->resource);
1145     list_init(&texture->rtv_list);
1146 
1147     desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
1148     desc.format = wined3dformat_from_d3dformat(format);
1149     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
1150     desc.multisample_quality = 0;
1151     desc.usage = usage & WINED3DUSAGE_MASK;
1152     desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP | WINED3DUSAGE_TEXTURE;
1153     desc.pool = pool;
1154     desc.width = edge_length;
1155     desc.height = edge_length;
1156     desc.depth = 1;
1157     desc.size = 0;
1158 
1159     if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC))
1160         flags |= WINED3D_TEXTURE_CREATE_MAPPABLE;
1161 
1162     if (!levels)
1163         levels = wined3d_log2i(edge_length) + 1;
1164 
1165     wined3d_mutex_lock();
1166     hr = wined3d_texture_create(device->wined3d_device, &desc, 6, levels, flags,
1167             NULL, texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
1168     wined3d_mutex_unlock();
1169     if (FAILED(hr))
1170     {
1171         WARN("Failed to create wined3d cube texture, hr %#x.\n", hr);
1172         return hr;
1173     }
1174 
1175     texture->parent_device = &device->IDirect3DDevice8_iface;
1176     IDirect3DDevice8_AddRef(texture->parent_device);
1177 
1178     return D3D_OK;
1179 }
1180 
1181 HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *device,
1182         UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
1183 {
1184     struct wined3d_resource_desc desc;
1185     HRESULT hr;
1186 
1187     texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl;
1188     d3d8_resource_init(&texture->resource);
1189     list_init(&texture->rtv_list);
1190 
1191     desc.resource_type = WINED3D_RTYPE_TEXTURE_3D;
1192     desc.format = wined3dformat_from_d3dformat(format);
1193     desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
1194     desc.multisample_quality = 0;
1195     desc.usage = usage & WINED3DUSAGE_MASK;
1196     desc.usage |= WINED3DUSAGE_TEXTURE;
1197     desc.pool = pool;
1198     desc.width = width;
1199     desc.height = height;
1200     desc.depth = depth;
1201     desc.size = 0;
1202 
1203     if (!levels)
1204         levels = wined3d_log2i(max(max(width, height), depth)) + 1;
1205 
1206     wined3d_mutex_lock();
1207     hr = wined3d_texture_create(device->wined3d_device, &desc, 1, levels, 0,
1208             NULL, texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
1209     wined3d_mutex_unlock();
1210     if (FAILED(hr))
1211     {
1212         WARN("Failed to create wined3d volume texture, hr %#x.\n", hr);
1213         return hr;
1214     }
1215 
1216     texture->parent_device = &device->IDirect3DDevice8_iface;
1217     IDirect3DDevice8_AddRef(texture->parent_device);
1218 
1219     return D3D_OK;
1220 }
1221