xref: /reactos/dll/directx/wine/d3d9/texture.c (revision 5c7ce447)
1  /*
2   * Copyright 2002-2005 Jason Edmeades
3   * Copyright 2002-2005 Raphael Junqueira
4   * Copyright 2005 Oliver Stieber
5   *
6   * This library is free software; you can redistribute it and/or
7   * modify it under the terms of the GNU Lesser General Public
8   * License as published by the Free Software Foundation; either
9   * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19   */
20  
21  #include "config.h"
22  #include "d3d9_private.h"
23  
24  WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
25  
26  static inline struct d3d9_texture *impl_from_IDirect3DTexture9(IDirect3DTexture9 *iface)
27  {
28      return CONTAINING_RECORD((IDirect3DBaseTexture9 *)iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
29  }
30  
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  
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  
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. */
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  
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. */
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
255  static D3DRESOURCETYPE WINAPI d3d9_texture_2d_GetType(IDirect3DTexture9 *iface)
256  {
257      TRACE("iface %p.\n", iface);
258  
259      return D3DRTYPE_TEXTURE;
260  }
261  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
653  static D3DRESOURCETYPE WINAPI d3d9_texture_cube_GetType(IDirect3DCubeTexture9 *iface)
654  {
655      TRACE("iface %p.\n", iface);
656  
657      return D3DRTYPE_CUBETEXTURE;
658  }
659  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
1071  static D3DRESOURCETYPE WINAPI d3d9_texture_3d_GetType(IDirect3DVolumeTexture9 *iface)
1072  {
1073      TRACE("iface %p.\n", iface);
1074  
1075      return D3DRTYPE_VOLUMETEXTURE;
1076  }
1077  
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  
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  
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  
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  
1128  static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_3d_GetAutoGenFilterType(IDirect3DVolumeTexture9 *iface)
1129  {
1130      TRACE("iface %p.\n", iface);
1131  
1132      return D3DTEXF_NONE;
1133  }
1134  
1135  static void WINAPI d3d9_texture_3d_GenerateMipSubLevels(IDirect3DVolumeTexture9 *iface)
1136  {
1137      TRACE("iface %p.\n", iface);
1138  }
1139  
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  
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  
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  
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  
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  
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  
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  
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  
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  
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