dmusic: Pass creation parameters to DMUSIC_CreateDirectMusicBufferImpl then allocate...
[wine] / dlls / d3d9 / texture.c
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(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
29 }
30
31 static inline struct d3d9_texture *impl_from_IDirect3DCubeTexture9(IDirect3DCubeTexture9 *iface)
32 {
33     return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface);
34 }
35
36 static HRESULT WINAPI d3d9_texture_2d_QueryInterface(IDirect3DTexture9 *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_IDirect3DTexture9)
41             || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9)
42             || IsEqualGUID(riid, &IID_IDirect3DResource9)
43             || IsEqualGUID(riid, &IID_IUnknown))
44     {
45         IDirect3DTexture9_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 d3d9_texture_2d_AddRef(IDirect3DTexture9 *iface)
57 {
58     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
59     ULONG ref = InterlockedIncrement(&texture->refcount);
60
61     TRACE("%p increasing refcount to %u.\n", iface, ref);
62
63     if (ref == 1)
64     {
65         IDirect3DDevice9Ex_AddRef(texture->parent_device);
66         wined3d_mutex_lock();
67         wined3d_texture_incref(texture->wined3d_texture);
68         wined3d_mutex_unlock();
69     }
70
71     return ref;
72 }
73
74 static ULONG WINAPI d3d9_texture_2d_Release(IDirect3DTexture9 *iface)
75 {
76     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
77     ULONG ref = InterlockedDecrement(&texture->refcount);
78
79     TRACE("%p decreasing refcount to %u.\n", iface, ref);
80
81     if (!ref)
82     {
83         IDirect3DDevice9Ex *parent_device = texture->parent_device;
84
85         wined3d_mutex_lock();
86         wined3d_texture_decref(texture->wined3d_texture);
87         wined3d_mutex_unlock();
88
89         /* Release the device last, as it may cause the device to be destroyed. */
90         IDirect3DDevice9Ex_Release(parent_device);
91     }
92     return ref;
93 }
94
95 static HRESULT WINAPI d3d9_texture_2d_GetDevice(IDirect3DTexture9 *iface, IDirect3DDevice9 **device)
96 {
97     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
98
99     TRACE("iface %p, device %p.\n", iface, device);
100
101     *device = (IDirect3DDevice9 *)texture->parent_device;
102     IDirect3DDevice9_AddRef(*device);
103
104     TRACE("Returning device %p.\n", *device);
105
106     return D3D_OK;
107 }
108
109 static HRESULT WINAPI d3d9_texture_2d_SetPrivateData(IDirect3DTexture9 *iface,
110         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
111 {
112     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
113     struct wined3d_resource *resource;
114     HRESULT hr;
115
116     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
117             iface, debugstr_guid(guid), data, data_size, flags);
118
119     wined3d_mutex_lock();
120     resource = wined3d_texture_get_resource(texture->wined3d_texture);
121     hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
122     wined3d_mutex_unlock();
123
124     return hr;
125 }
126
127 static HRESULT WINAPI d3d9_texture_2d_GetPrivateData(IDirect3DTexture9 *iface,
128         REFGUID guid, void *data, DWORD *data_size)
129 {
130     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
131     struct wined3d_resource *resource;
132     HRESULT hr;
133
134     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
135             iface, debugstr_guid(guid), data, data_size);
136
137     wined3d_mutex_lock();
138     resource = wined3d_texture_get_resource(texture->wined3d_texture);
139     hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
140     wined3d_mutex_unlock();
141
142     return hr;
143 }
144
145 static HRESULT WINAPI d3d9_texture_2d_FreePrivateData(IDirect3DTexture9 *iface, REFGUID guid)
146 {
147     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
148     struct wined3d_resource *resource;
149     HRESULT hr;
150
151     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
152
153     wined3d_mutex_lock();
154     resource = wined3d_texture_get_resource(texture->wined3d_texture);
155     hr = wined3d_resource_free_private_data(resource, guid);
156     wined3d_mutex_unlock();
157
158     return hr;
159 }
160
161 static DWORD WINAPI d3d9_texture_2d_SetPriority(IDirect3DTexture9 *iface, DWORD priority)
162 {
163     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
164     DWORD ret;
165
166     TRACE("iface %p, priority %u.\n", iface, priority);
167
168     wined3d_mutex_lock();
169     ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
170     wined3d_mutex_unlock();
171
172     return ret;
173 }
174
175 static DWORD WINAPI d3d9_texture_2d_GetPriority(IDirect3DTexture9 *iface)
176 {
177     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
178     DWORD ret;
179
180     TRACE("iface %p.\n", iface);
181
182     wined3d_mutex_lock();
183     ret = wined3d_texture_get_priority(texture->wined3d_texture);
184     wined3d_mutex_unlock();
185
186     return ret;
187 }
188
189 static void WINAPI d3d9_texture_2d_PreLoad(IDirect3DTexture9 *iface)
190 {
191     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
192
193     TRACE("iface %p.\n", iface);
194
195     wined3d_mutex_lock();
196     wined3d_texture_preload(texture->wined3d_texture);
197     wined3d_mutex_unlock();
198 }
199
200 static D3DRESOURCETYPE WINAPI d3d9_texture_2d_GetType(IDirect3DTexture9 *iface)
201 {
202     TRACE("iface %p.\n", iface);
203
204     return D3DRTYPE_TEXTURE;
205 }
206
207 static DWORD WINAPI d3d9_texture_2d_SetLOD(IDirect3DTexture9 *iface, DWORD lod)
208 {
209     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
210     DWORD ret;
211
212     TRACE("iface %p, lod %u.\n", iface, lod);
213
214     wined3d_mutex_lock();
215     ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
216     wined3d_mutex_unlock();
217
218     return ret;
219 }
220
221 static DWORD WINAPI d3d9_texture_2d_GetLOD(IDirect3DTexture9 *iface)
222 {
223     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
224     DWORD ret;
225
226     TRACE("iface %p.\n", iface);
227
228     wined3d_mutex_lock();
229     ret = wined3d_texture_get_lod(texture->wined3d_texture);
230     wined3d_mutex_unlock();
231
232     return ret;
233 }
234
235 static DWORD WINAPI d3d9_texture_2d_GetLevelCount(IDirect3DTexture9 *iface)
236 {
237     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
238     DWORD ret;
239
240     TRACE("iface %p.\n", iface);
241
242     wined3d_mutex_lock();
243     ret = wined3d_texture_get_level_count(texture->wined3d_texture);
244     wined3d_mutex_unlock();
245
246     return ret;
247 }
248
249 static HRESULT WINAPI d3d9_texture_2d_SetAutoGenFilterType(IDirect3DTexture9 *iface, D3DTEXTUREFILTERTYPE filter_type)
250 {
251     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
252     HRESULT hr;
253
254     TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
255
256     wined3d_mutex_lock();
257     hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
258             (enum wined3d_texture_filter_type)filter_type);
259     wined3d_mutex_unlock();
260
261     return hr;
262 }
263
264 static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_2d_GetAutoGenFilterType(IDirect3DTexture9 *iface)
265 {
266     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
267     D3DTEXTUREFILTERTYPE ret;
268
269     TRACE("iface %p.\n", iface);
270
271     wined3d_mutex_lock();
272     ret = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
273     wined3d_mutex_unlock();
274
275     return ret;
276 }
277
278 static void WINAPI d3d9_texture_2d_GenerateMipSubLevels(IDirect3DTexture9 *iface)
279 {
280     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
281
282     TRACE("iface %p.\n", iface);
283
284     wined3d_mutex_lock();
285     wined3d_texture_generate_mipmaps(texture->wined3d_texture);
286     wined3d_mutex_unlock();
287 }
288
289 static HRESULT WINAPI d3d9_texture_2d_GetLevelDesc(IDirect3DTexture9 *iface, UINT level, D3DSURFACE_DESC *desc)
290 {
291     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
292     struct wined3d_resource *sub_resource;
293     HRESULT hr = D3D_OK;
294
295     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
296
297     wined3d_mutex_lock();
298     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
299         hr = D3DERR_INVALIDCALL;
300     else
301     {
302         struct wined3d_resource_desc wined3d_desc;
303
304         wined3d_resource_get_desc(sub_resource, &wined3d_desc);
305         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
306         desc->Type = wined3d_desc.resource_type;
307         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
308         desc->Pool = wined3d_desc.pool;
309         desc->MultiSampleType = wined3d_desc.multisample_type;
310         desc->MultiSampleQuality = wined3d_desc.multisample_quality;
311         desc->Width = wined3d_desc.width;
312         desc->Height = wined3d_desc.height;
313     }
314     wined3d_mutex_unlock();
315
316     return hr;
317 }
318
319 static HRESULT WINAPI d3d9_texture_2d_GetSurfaceLevel(IDirect3DTexture9 *iface,
320         UINT level, IDirect3DSurface9 **surface)
321 {
322     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
323     struct wined3d_resource *sub_resource;
324
325     TRACE("iface %p, level %u, surface %p.\n", iface, level, surface);
326
327     wined3d_mutex_lock();
328     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
329     {
330         wined3d_mutex_unlock();
331         return D3DERR_INVALIDCALL;
332     }
333
334     *surface = wined3d_resource_get_parent(sub_resource);
335     IDirect3DSurface9_AddRef(*surface);
336     wined3d_mutex_unlock();
337
338     return D3D_OK;
339 }
340
341 static HRESULT WINAPI d3d9_texture_2d_LockRect(IDirect3DTexture9 *iface,
342         UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
343 {
344     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
345     struct wined3d_resource *sub_resource;
346     HRESULT hr;
347
348     TRACE("iface %p, level %u, locked_rect %p, rect %p, flags %#x.\n",
349             iface, level, locked_rect, rect, flags);
350
351     wined3d_mutex_lock();
352     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
353         hr = D3DERR_INVALIDCALL;
354     else
355         hr = IDirect3DSurface9_LockRect((IDirect3DSurface9 *)wined3d_resource_get_parent(sub_resource),
356                 locked_rect, rect, flags);
357     wined3d_mutex_unlock();
358
359     return hr;
360 }
361
362 static HRESULT WINAPI d3d9_texture_2d_UnlockRect(IDirect3DTexture9 *iface, UINT level)
363 {
364     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
365     struct wined3d_resource *sub_resource;
366     HRESULT hr;
367
368     TRACE("iface %p, level %u.\n", iface, level);
369
370     wined3d_mutex_lock();
371     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
372         hr = D3DERR_INVALIDCALL;
373     else
374         hr = IDirect3DSurface9_UnlockRect((IDirect3DSurface9 *)wined3d_resource_get_parent(sub_resource));
375     wined3d_mutex_unlock();
376
377     return hr;
378 }
379
380 static HRESULT WINAPI d3d9_texture_2d_AddDirtyRect(IDirect3DTexture9 *iface, const RECT *dirty_rect)
381 {
382     struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface);
383     HRESULT hr;
384
385     TRACE("iface %p, dirty_rect %s.\n",
386             iface, wine_dbgstr_rect(dirty_rect));
387
388     wined3d_mutex_lock();
389     if (!dirty_rect)
390         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, NULL);
391     else
392     {
393         struct wined3d_box dirty_region;
394
395         dirty_region.left = dirty_rect->left;
396         dirty_region.top = dirty_rect->top;
397         dirty_region.right = dirty_rect->right;
398         dirty_region.bottom = dirty_rect->bottom;
399         dirty_region.front = 0;
400         dirty_region.back = 1;
401         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, &dirty_region);
402     }
403     wined3d_mutex_unlock();
404
405     return hr;
406 }
407
408 static const IDirect3DTexture9Vtbl d3d9_texture_2d_vtbl =
409 {
410     /* IUnknown */
411     d3d9_texture_2d_QueryInterface,
412     d3d9_texture_2d_AddRef,
413     d3d9_texture_2d_Release,
414      /* IDirect3DResource9 */
415     d3d9_texture_2d_GetDevice,
416     d3d9_texture_2d_SetPrivateData,
417     d3d9_texture_2d_GetPrivateData,
418     d3d9_texture_2d_FreePrivateData,
419     d3d9_texture_2d_SetPriority,
420     d3d9_texture_2d_GetPriority,
421     d3d9_texture_2d_PreLoad,
422     d3d9_texture_2d_GetType,
423     /* IDirect3dBaseTexture9 */
424     d3d9_texture_2d_SetLOD,
425     d3d9_texture_2d_GetLOD,
426     d3d9_texture_2d_GetLevelCount,
427     d3d9_texture_2d_SetAutoGenFilterType,
428     d3d9_texture_2d_GetAutoGenFilterType,
429     d3d9_texture_2d_GenerateMipSubLevels,
430     /* IDirect3DTexture9 */
431     d3d9_texture_2d_GetLevelDesc,
432     d3d9_texture_2d_GetSurfaceLevel,
433     d3d9_texture_2d_LockRect,
434     d3d9_texture_2d_UnlockRect,
435     d3d9_texture_2d_AddDirtyRect,
436 };
437
438 static HRESULT WINAPI d3d9_texture_cube_QueryInterface(IDirect3DCubeTexture9 *iface, REFIID riid, void **out)
439 {
440     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
441
442     if (IsEqualGUID(riid, &IID_IDirect3DCubeTexture9)
443             || IsEqualGUID(riid, &IID_IDirect3DBaseTexture9)
444             || IsEqualGUID(riid, &IID_IDirect3DResource9)
445             || IsEqualGUID(riid, &IID_IUnknown))
446     {
447         IDirect3DCubeTexture9_AddRef(iface);
448         *out = iface;
449         return S_OK;
450     }
451
452     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
453
454     *out = NULL;
455     return E_NOINTERFACE;
456 }
457
458 static ULONG WINAPI d3d9_texture_cube_AddRef(IDirect3DCubeTexture9 *iface)
459 {
460     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
461     ULONG ref = InterlockedIncrement(&texture->refcount);
462
463     TRACE("%p increasing refcount to %u.\n", iface, ref);
464
465     if (ref == 1)
466     {
467         IDirect3DDevice9Ex_AddRef(texture->parent_device);
468         wined3d_mutex_lock();
469         wined3d_texture_incref(texture->wined3d_texture);
470         wined3d_mutex_unlock();
471     }
472
473     return ref;
474 }
475
476 static ULONG WINAPI d3d9_texture_cube_Release(IDirect3DCubeTexture9 *iface)
477 {
478     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
479     ULONG ref = InterlockedDecrement(&texture->refcount);
480
481     TRACE("%p decreasing refcount to %u.\n", iface, ref);
482
483     if (!ref)
484     {
485         IDirect3DDevice9Ex *parent_device = texture->parent_device;
486
487         TRACE("Releasing child %p.\n", texture->wined3d_texture);
488
489         wined3d_mutex_lock();
490         wined3d_texture_decref(texture->wined3d_texture);
491         wined3d_mutex_unlock();
492
493         /* Release the device last, as it may cause the device to be destroyed. */
494         IDirect3DDevice9Ex_Release(parent_device);
495     }
496     return ref;
497 }
498
499 static HRESULT WINAPI d3d9_texture_cube_GetDevice(IDirect3DCubeTexture9 *iface, IDirect3DDevice9 **device)
500 {
501     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
502
503     TRACE("iface %p, device %p.\n", iface, device);
504
505     *device = (IDirect3DDevice9 *)texture->parent_device;
506     IDirect3DDevice9_AddRef(*device);
507
508     TRACE("Returning device %p.\n", *device);
509
510     return D3D_OK;
511 }
512
513 static HRESULT WINAPI d3d9_texture_cube_SetPrivateData(IDirect3DCubeTexture9 *iface,
514         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
515 {
516     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
517     struct wined3d_resource *resource;
518     HRESULT hr;
519
520     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
521             iface, debugstr_guid(guid), data, data_size, flags);
522
523     wined3d_mutex_lock();
524     resource = wined3d_texture_get_resource(texture->wined3d_texture);
525     hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
526     wined3d_mutex_unlock();
527
528     return hr;
529 }
530
531 static HRESULT WINAPI d3d9_texture_cube_GetPrivateData(IDirect3DCubeTexture9 *iface,
532         REFGUID guid, void *data, DWORD *data_size)
533 {
534     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
535     struct wined3d_resource *resource;
536     HRESULT hr;
537
538     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
539             iface, debugstr_guid(guid), data, data_size);
540
541     wined3d_mutex_lock();
542     resource = wined3d_texture_get_resource(texture->wined3d_texture);
543     hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
544     wined3d_mutex_unlock();
545
546     return hr;
547 }
548
549 static HRESULT WINAPI d3d9_texture_cube_FreePrivateData(IDirect3DCubeTexture9 *iface, REFGUID guid)
550 {
551     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
552     struct wined3d_resource *resource;
553     HRESULT hr;
554
555     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
556
557     wined3d_mutex_lock();
558     resource = wined3d_texture_get_resource(texture->wined3d_texture);
559     hr = wined3d_resource_free_private_data(resource, guid);
560     wined3d_mutex_unlock();
561
562     return hr;
563 }
564
565 static DWORD WINAPI d3d9_texture_cube_SetPriority(IDirect3DCubeTexture9 *iface, DWORD priority)
566 {
567     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
568     DWORD ret;
569
570     TRACE("iface %p, priority %u.\n", iface, priority);
571
572     wined3d_mutex_lock();
573     ret = wined3d_texture_set_priority(texture->wined3d_texture, priority);
574     wined3d_mutex_unlock();
575
576     return ret;
577 }
578
579 static DWORD WINAPI d3d9_texture_cube_GetPriority(IDirect3DCubeTexture9 *iface)
580 {
581     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
582     DWORD ret;
583
584     TRACE("iface %p.\n", iface);
585
586     wined3d_mutex_lock();
587     ret = wined3d_texture_get_priority(texture->wined3d_texture);
588     wined3d_mutex_unlock();
589
590     return ret;
591 }
592
593 static void WINAPI d3d9_texture_cube_PreLoad(IDirect3DCubeTexture9 *iface)
594 {
595     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
596
597     TRACE("iface %p.\n", iface);
598
599     wined3d_mutex_lock();
600     wined3d_texture_preload(texture->wined3d_texture);
601     wined3d_mutex_unlock();
602 }
603
604 static D3DRESOURCETYPE WINAPI d3d9_texture_cube_GetType(IDirect3DCubeTexture9 *iface)
605 {
606     TRACE("iface %p.\n", iface);
607
608     return D3DRTYPE_CUBETEXTURE;
609 }
610
611 static DWORD WINAPI d3d9_texture_cube_SetLOD(IDirect3DCubeTexture9 *iface, DWORD lod)
612 {
613     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
614     DWORD ret;
615
616     TRACE("iface %p, lod %u.\n", iface, lod);
617
618     wined3d_mutex_lock();
619     ret = wined3d_texture_set_lod(texture->wined3d_texture, lod);
620     wined3d_mutex_unlock();
621
622     return ret;
623 }
624
625 static DWORD WINAPI d3d9_texture_cube_GetLOD(IDirect3DCubeTexture9 *iface)
626 {
627     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
628     DWORD ret;
629
630     TRACE("iface %p.\n", iface);
631
632     wined3d_mutex_lock();
633     ret = wined3d_texture_get_lod(texture->wined3d_texture);
634     wined3d_mutex_unlock();
635
636     return ret;
637 }
638
639 static DWORD WINAPI d3d9_texture_cube_GetLevelCount(IDirect3DCubeTexture9 *iface)
640 {
641     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
642     DWORD ret;
643
644     TRACE("iface %p.\n", iface);
645
646     wined3d_mutex_lock();
647     ret = wined3d_texture_get_level_count(texture->wined3d_texture);
648     wined3d_mutex_unlock();
649
650     return ret;
651 }
652
653 static HRESULT WINAPI d3d9_texture_cube_SetAutoGenFilterType(IDirect3DCubeTexture9 *iface,
654         D3DTEXTUREFILTERTYPE filter_type)
655 {
656     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
657     HRESULT hr;
658
659     TRACE("iface %p, filter_type %#x.\n", iface, filter_type);
660
661     wined3d_mutex_lock();
662     hr = wined3d_texture_set_autogen_filter_type(texture->wined3d_texture,
663             (enum wined3d_texture_filter_type)filter_type);
664     wined3d_mutex_unlock();
665
666     return hr;
667 }
668
669 static D3DTEXTUREFILTERTYPE WINAPI d3d9_texture_cube_GetAutoGenFilterType(IDirect3DCubeTexture9 *iface)
670 {
671     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
672     D3DTEXTUREFILTERTYPE ret;
673
674     TRACE("iface %p.\n", iface);
675
676     wined3d_mutex_lock();
677     ret = (D3DTEXTUREFILTERTYPE)wined3d_texture_get_autogen_filter_type(texture->wined3d_texture);
678     wined3d_mutex_unlock();
679
680     return ret;
681 }
682
683 static void WINAPI d3d9_texture_cube_GenerateMipSubLevels(IDirect3DCubeTexture9 *iface)
684 {
685     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
686
687     TRACE("iface %p.\n", iface);
688
689     wined3d_mutex_lock();
690     wined3d_texture_generate_mipmaps(texture->wined3d_texture);
691     wined3d_mutex_unlock();
692 }
693
694 static HRESULT WINAPI d3d9_texture_cube_GetLevelDesc(IDirect3DCubeTexture9 *iface, UINT level, D3DSURFACE_DESC *desc)
695 {
696     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
697     struct wined3d_resource *sub_resource;
698     HRESULT hr = D3D_OK;
699
700     TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
701
702     wined3d_mutex_lock();
703     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level)))
704         hr = D3DERR_INVALIDCALL;
705     else
706     {
707         struct wined3d_resource_desc wined3d_desc;
708
709         wined3d_resource_get_desc(sub_resource, &wined3d_desc);
710         desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
711         desc->Type = wined3d_desc.resource_type;
712         desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
713         desc->Pool = wined3d_desc.pool;
714         desc->MultiSampleType = wined3d_desc.multisample_type;
715         desc->MultiSampleQuality = wined3d_desc.multisample_quality;
716         desc->Width = wined3d_desc.width;
717         desc->Height = wined3d_desc.height;
718     }
719     wined3d_mutex_unlock();
720
721     return hr;
722 }
723
724 static HRESULT WINAPI d3d9_texture_cube_GetCubeMapSurface(IDirect3DCubeTexture9 *iface,
725         D3DCUBEMAP_FACES face, UINT level, IDirect3DSurface9 **surface)
726 {
727     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
728     struct wined3d_resource *sub_resource;
729     UINT sub_resource_idx;
730
731     TRACE("iface %p, face %#x, level %u, surface %p.\n", iface, face, level, surface);
732
733     wined3d_mutex_lock();
734     sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
735     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
736     {
737         wined3d_mutex_unlock();
738         return D3DERR_INVALIDCALL;
739     }
740
741     *surface = wined3d_resource_get_parent(sub_resource);
742     IDirect3DSurface9_AddRef(*surface);
743     wined3d_mutex_unlock();
744
745     return D3D_OK;
746 }
747
748 static HRESULT WINAPI d3d9_texture_cube_LockRect(IDirect3DCubeTexture9 *iface,
749         D3DCUBEMAP_FACES face, UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect,
750         DWORD flags)
751 {
752     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
753     struct wined3d_resource *sub_resource;
754     UINT sub_resource_idx;
755     HRESULT hr;
756
757     TRACE("iface %p, face %#x, level %u, locked_rect %p, rect %p, flags %#x.\n",
758             iface, face, level, locked_rect, rect, flags);
759
760     wined3d_mutex_lock();
761     sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
762     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
763         hr = D3DERR_INVALIDCALL;
764     else
765         hr = IDirect3DSurface9_LockRect((IDirect3DSurface9 *)wined3d_resource_get_parent(sub_resource),
766                 locked_rect, rect, flags);
767     wined3d_mutex_unlock();
768
769     return hr;
770 }
771
772 static HRESULT WINAPI d3d9_texture_cube_UnlockRect(IDirect3DCubeTexture9 *iface,
773         D3DCUBEMAP_FACES face, UINT level)
774 {
775     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
776     struct wined3d_resource *sub_resource;
777     UINT sub_resource_idx;
778     HRESULT hr;
779
780     TRACE("iface %p, face %#x, level %u.\n", iface, face, level);
781
782     wined3d_mutex_lock();
783     sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level;
784     if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
785         hr = D3DERR_INVALIDCALL;
786     else
787         hr = IDirect3DSurface9_UnlockRect((IDirect3DSurface9 *)wined3d_resource_get_parent(sub_resource));
788     wined3d_mutex_unlock();
789
790     return hr;
791 }
792
793 static HRESULT  WINAPI d3d9_texture_cube_AddDirtyRect(IDirect3DCubeTexture9 *iface,
794         D3DCUBEMAP_FACES face, const RECT *dirty_rect)
795 {
796     struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface);
797     HRESULT hr;
798
799     TRACE("iface %p, face %#x, dirty_rect %s.\n",
800             iface, face, wine_dbgstr_rect(dirty_rect));
801
802     wined3d_mutex_lock();
803     if (!dirty_rect)
804         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, NULL);
805     else
806     {
807         struct wined3d_box dirty_region;
808
809         dirty_region.left = dirty_rect->left;
810         dirty_region.top = dirty_rect->top;
811         dirty_region.right = dirty_rect->right;
812         dirty_region.bottom = dirty_rect->bottom;
813         dirty_region.front = 0;
814         dirty_region.back = 1;
815         hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, &dirty_region);
816     }
817     wined3d_mutex_unlock();
818
819     return hr;
820 }
821
822 static const IDirect3DCubeTexture9Vtbl d3d9_texture_cube_vtbl =
823 {
824     /* IUnknown */
825     d3d9_texture_cube_QueryInterface,
826     d3d9_texture_cube_AddRef,
827     d3d9_texture_cube_Release,
828     /* IDirect3DResource9 */
829     d3d9_texture_cube_GetDevice,
830     d3d9_texture_cube_SetPrivateData,
831     d3d9_texture_cube_GetPrivateData,
832     d3d9_texture_cube_FreePrivateData,
833     d3d9_texture_cube_SetPriority,
834     d3d9_texture_cube_GetPriority,
835     d3d9_texture_cube_PreLoad,
836     d3d9_texture_cube_GetType,
837     /* IDirect3DBaseTexture9 */
838     d3d9_texture_cube_SetLOD,
839     d3d9_texture_cube_GetLOD,
840     d3d9_texture_cube_GetLevelCount,
841     d3d9_texture_cube_SetAutoGenFilterType,
842     d3d9_texture_cube_GetAutoGenFilterType,
843     d3d9_texture_cube_GenerateMipSubLevels,
844     /* IDirect3DCubeTexture9 */
845     d3d9_texture_cube_GetLevelDesc,
846     d3d9_texture_cube_GetCubeMapSurface,
847     d3d9_texture_cube_LockRect,
848     d3d9_texture_cube_UnlockRect,
849     d3d9_texture_cube_AddDirtyRect,
850 };
851
852 static void STDMETHODCALLTYPE d3d9_texture_wined3d_object_destroyed(void *parent)
853 {
854     HeapFree(GetProcessHeap(), 0, parent);
855 }
856
857 static const struct wined3d_parent_ops d3d9_texture_wined3d_parent_ops =
858 {
859     d3d9_texture_wined3d_object_destroyed,
860 };
861
862 HRESULT texture_init(struct d3d9_texture *texture, IDirect3DDevice9Impl *device,
863         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
864 {
865     HRESULT hr;
866
867     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_2d_vtbl;
868     texture->refcount = 1;
869
870     wined3d_mutex_lock();
871     hr = wined3d_texture_create_2d(device->wined3d_device, width, height, levels,
872             usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool,
873             texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
874     wined3d_mutex_unlock();
875     if (FAILED(hr))
876     {
877         WARN("Failed to create wined3d texture, hr %#x.\n", hr);
878         return hr;
879     }
880
881     texture->parent_device = &device->IDirect3DDevice9Ex_iface;
882     IDirect3DDevice9Ex_AddRef(texture->parent_device);
883
884     return D3D_OK;
885 }
886
887 HRESULT cubetexture_init(struct d3d9_texture *texture, IDirect3DDevice9Impl *device,
888         UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
889 {
890     HRESULT hr;
891
892     texture->IDirect3DBaseTexture9_iface.lpVtbl = (const IDirect3DBaseTexture9Vtbl *)&d3d9_texture_cube_vtbl;
893     texture->refcount = 1;
894
895     wined3d_mutex_lock();
896     hr = wined3d_texture_create_cube(device->wined3d_device, edge_length,
897             levels, usage, wined3dformat_from_d3dformat(format), pool, texture,
898             &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
899     wined3d_mutex_unlock();
900     if (FAILED(hr))
901     {
902         WARN("Failed to create wined3d cube texture, hr %#x.\n", hr);
903         return hr;
904     }
905
906     texture->parent_device = &device->IDirect3DDevice9Ex_iface;
907     IDirect3DDevice9Ex_AddRef(texture->parent_device);
908
909     return D3D_OK;
910 }