dmsynth: Dump data passed to Download method.
[wine] / dlls / d3d8 / buffer.c
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 "config.h"
20 #include "d3d8_private.h"
21
22 WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
23
24 static inline struct d3d8_vertexbuffer *impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface)
25 {
26     return CONTAINING_RECORD(iface, struct d3d8_vertexbuffer, IDirect3DVertexBuffer8_iface);
27 }
28
29 static HRESULT WINAPI d3d8_vertexbuffer_QueryInterface(IDirect3DVertexBuffer8 *iface, REFIID riid, void **object)
30 {
31     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
32
33     if (IsEqualGUID(riid, &IID_IDirect3DVertexBuffer8)
34             || IsEqualGUID(riid, &IID_IDirect3DResource8)
35             || IsEqualGUID(riid, &IID_IUnknown))
36     {
37         IDirect3DVertexBuffer8_AddRef(iface);
38         *object = iface;
39         return S_OK;
40     }
41
42     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
43
44     *object = NULL;
45     return E_NOINTERFACE;
46 }
47
48 static ULONG WINAPI d3d8_vertexbuffer_AddRef(IDirect3DVertexBuffer8 *iface)
49 {
50     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
51     ULONG refcount = InterlockedIncrement(&buffer->refcount);
52
53     TRACE("%p increasing refcount to %u.\n", iface, refcount);
54
55     if (refcount == 1)
56     {
57         IDirect3DDevice8_AddRef(buffer->parent_device);
58         wined3d_mutex_lock();
59         wined3d_buffer_incref(buffer->wined3d_buffer);
60         wined3d_mutex_unlock();
61     }
62
63     return refcount;
64 }
65
66 static ULONG WINAPI d3d8_vertexbuffer_Release(IDirect3DVertexBuffer8 *iface)
67 {
68     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
69     ULONG refcount = InterlockedDecrement(&buffer->refcount);
70
71     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
72
73     if (!refcount)
74     {
75         IDirect3DDevice8 *device = buffer->parent_device;
76
77         wined3d_mutex_lock();
78         wined3d_buffer_decref(buffer->wined3d_buffer);
79         wined3d_mutex_unlock();
80
81         /* Release the device last, as it may cause the device to be destroyed. */
82         IDirect3DDevice8_Release(device);
83     }
84
85     return refcount;
86 }
87
88 static HRESULT WINAPI d3d8_vertexbuffer_GetDevice(IDirect3DVertexBuffer8 *iface,
89         IDirect3DDevice8 **device)
90 {
91     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
92
93     TRACE("iface %p, device %p.\n", iface, device);
94
95     *device = buffer->parent_device;
96     IDirect3DDevice8_AddRef(*device);
97
98     TRACE("Returning device %p.\n", *device);
99
100     return D3D_OK;
101 }
102
103 static HRESULT WINAPI d3d8_vertexbuffer_SetPrivateData(IDirect3DVertexBuffer8 *iface,
104         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
105 {
106     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
107     struct wined3d_resource *resource;
108     HRESULT hr;
109
110     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
111             iface, debugstr_guid(guid), data, data_size, flags);
112
113     wined3d_mutex_lock();
114     resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
115     hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
116     wined3d_mutex_unlock();
117
118     return hr;
119 }
120
121 static HRESULT WINAPI d3d8_vertexbuffer_GetPrivateData(IDirect3DVertexBuffer8 *iface,
122         REFGUID guid, void *data, DWORD *data_size)
123 {
124     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
125     struct wined3d_resource *resource;
126     HRESULT hr;
127
128     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
129             iface, debugstr_guid(guid), data, data_size);
130
131     wined3d_mutex_lock();
132     resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
133     hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
134     wined3d_mutex_unlock();
135
136     return hr;
137 }
138
139 static HRESULT WINAPI d3d8_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer8 *iface, REFGUID guid)
140 {
141     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
142     struct wined3d_resource *resource;
143     HRESULT hr;
144
145     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
146
147     wined3d_mutex_lock();
148     resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
149     hr = wined3d_resource_free_private_data(resource, guid);
150     wined3d_mutex_unlock();
151
152     return hr;
153 }
154
155 static DWORD WINAPI d3d8_vertexbuffer_SetPriority(IDirect3DVertexBuffer8 *iface, DWORD priority)
156 {
157     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
158     DWORD previous;
159
160     TRACE("iface %p, priority %u.\n", iface, priority);
161
162     wined3d_mutex_lock();
163     previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
164     wined3d_mutex_unlock();
165
166     return previous;
167 }
168
169 static DWORD WINAPI d3d8_vertexbuffer_GetPriority(IDirect3DVertexBuffer8 *iface)
170 {
171     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
172     DWORD priority;
173
174     TRACE("iface %p.\n", iface);
175
176     wined3d_mutex_lock();
177     priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
178     wined3d_mutex_unlock();
179
180     return priority;
181 }
182
183 static void WINAPI d3d8_vertexbuffer_PreLoad(IDirect3DVertexBuffer8 *iface)
184 {
185     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
186
187     TRACE("iface %p.\n", iface);
188
189     wined3d_mutex_lock();
190     wined3d_buffer_preload(buffer->wined3d_buffer);
191     wined3d_mutex_unlock();
192 }
193
194 static D3DRESOURCETYPE WINAPI d3d8_vertexbuffer_GetType(IDirect3DVertexBuffer8 *iface)
195 {
196     TRACE("iface %p.\n", iface);
197
198     return D3DRTYPE_VERTEXBUFFER;
199 }
200
201 static HRESULT WINAPI d3d8_vertexbuffer_Lock(IDirect3DVertexBuffer8 *iface, UINT offset, UINT size,
202         BYTE **data, DWORD flags)
203 {
204     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
205     HRESULT hr;
206
207     TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
208             iface, offset, size, data, flags);
209
210     wined3d_mutex_lock();
211     hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, data, flags);
212     wined3d_mutex_unlock();
213
214     return hr;
215 }
216
217 static HRESULT WINAPI d3d8_vertexbuffer_Unlock(IDirect3DVertexBuffer8 *iface)
218 {
219     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
220
221     TRACE("iface %p.\n", iface);
222
223     wined3d_mutex_lock();
224     wined3d_buffer_unmap(buffer->wined3d_buffer);
225     wined3d_mutex_unlock();
226
227     return D3D_OK;
228 }
229
230 static HRESULT WINAPI d3d8_vertexbuffer_GetDesc(IDirect3DVertexBuffer8 *iface,
231         D3DVERTEXBUFFER_DESC *desc)
232 {
233     struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
234     struct wined3d_resource_desc wined3d_desc;
235     struct wined3d_resource *wined3d_resource;
236
237     TRACE("iface %p, desc %p.\n", iface, desc);
238
239     wined3d_mutex_lock();
240     wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
241     wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
242     wined3d_mutex_unlock();
243
244     desc->Type = D3DRTYPE_VERTEXBUFFER;
245     desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
246     desc->Pool = wined3d_desc.pool;
247     desc->Size = wined3d_desc.size;
248     desc->FVF = buffer->fvf;
249     desc->Format = D3DFMT_VERTEXDATA;
250
251     return D3D_OK;
252 }
253
254 static const IDirect3DVertexBuffer8Vtbl Direct3DVertexBuffer8_Vtbl =
255 {
256     /* IUnknown */
257     d3d8_vertexbuffer_QueryInterface,
258     d3d8_vertexbuffer_AddRef,
259     d3d8_vertexbuffer_Release,
260     /* IDirect3DResource8 */
261     d3d8_vertexbuffer_GetDevice,
262     d3d8_vertexbuffer_SetPrivateData,
263     d3d8_vertexbuffer_GetPrivateData,
264     d3d8_vertexbuffer_FreePrivateData,
265     d3d8_vertexbuffer_SetPriority,
266     d3d8_vertexbuffer_GetPriority,
267     d3d8_vertexbuffer_PreLoad,
268     d3d8_vertexbuffer_GetType,
269     /* IDirect3DVertexBuffer8 */
270     d3d8_vertexbuffer_Lock,
271     d3d8_vertexbuffer_Unlock,
272     d3d8_vertexbuffer_GetDesc,
273 };
274
275 static void STDMETHODCALLTYPE d3d8_vertexbuffer_wined3d_object_destroyed(void *parent)
276 {
277     HeapFree(GetProcessHeap(), 0, parent);
278 }
279
280 static const struct wined3d_parent_ops d3d8_vertexbuffer_wined3d_parent_ops =
281 {
282     d3d8_vertexbuffer_wined3d_object_destroyed,
283 };
284
285 HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *device,
286         UINT size, DWORD usage, DWORD fvf, D3DPOOL pool)
287 {
288     HRESULT hr;
289
290     buffer->IDirect3DVertexBuffer8_iface.lpVtbl = &Direct3DVertexBuffer8_Vtbl;
291     buffer->refcount = 1;
292     buffer->fvf = fvf;
293
294     wined3d_mutex_lock();
295     hr = wined3d_buffer_create_vb(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
296             (enum wined3d_pool)pool, buffer, &d3d8_vertexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
297     wined3d_mutex_unlock();
298     if (FAILED(hr))
299     {
300         WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
301         return hr;
302     }
303
304     buffer->parent_device = &device->IDirect3DDevice8_iface;
305     IDirect3DDevice8_AddRef(buffer->parent_device);
306
307     return D3D_OK;
308 }
309
310 struct d3d8_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface)
311 {
312     if (!iface)
313         return NULL;
314     assert(iface->lpVtbl == &Direct3DVertexBuffer8_Vtbl);
315
316     return impl_from_IDirect3DVertexBuffer8(iface);
317 }
318
319 static inline struct d3d8_indexbuffer *impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface)
320 {
321     return CONTAINING_RECORD(iface, struct d3d8_indexbuffer, IDirect3DIndexBuffer8_iface);
322 }
323
324 static HRESULT WINAPI d3d8_indexbuffer_QueryInterface(IDirect3DIndexBuffer8 *iface, REFIID riid, void **object)
325 {
326     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
327
328     if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer8)
329             || IsEqualGUID(riid, &IID_IDirect3DResource8)
330             || IsEqualGUID(riid, &IID_IUnknown))
331     {
332         IDirect3DIndexBuffer8_AddRef(iface);
333         *object = iface;
334         return S_OK;
335     }
336
337     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
338
339     *object = NULL;
340     return E_NOINTERFACE;
341 }
342
343 static ULONG WINAPI d3d8_indexbuffer_AddRef(IDirect3DIndexBuffer8 *iface)
344 {
345     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
346     ULONG refcount = InterlockedIncrement(&buffer->refcount);
347
348     TRACE("%p increasing refcount to %u.\n", iface, refcount);
349
350     if (refcount == 1)
351     {
352         IDirect3DDevice8_AddRef(buffer->parent_device);
353         wined3d_mutex_lock();
354         wined3d_buffer_incref(buffer->wined3d_buffer);
355         wined3d_mutex_unlock();
356     }
357
358     return refcount;
359 }
360
361 static ULONG WINAPI d3d8_indexbuffer_Release(IDirect3DIndexBuffer8 *iface)
362 {
363     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
364     ULONG refcount = InterlockedDecrement(&buffer->refcount);
365
366     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
367
368     if (!refcount)
369     {
370         IDirect3DDevice8 *device = buffer->parent_device;
371
372         wined3d_mutex_lock();
373         wined3d_buffer_decref(buffer->wined3d_buffer);
374         wined3d_mutex_unlock();
375
376         /* Release the device last, as it may cause the device to be destroyed. */
377         IDirect3DDevice8_Release(device);
378     }
379
380     return refcount;
381 }
382
383 static HRESULT WINAPI d3d8_indexbuffer_GetDevice(IDirect3DIndexBuffer8 *iface,
384         IDirect3DDevice8 **device)
385 {
386     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
387
388     TRACE("iface %p, device %p.\n", iface, device);
389
390     *device = buffer->parent_device;
391     IDirect3DDevice8_AddRef(*device);
392
393     TRACE("Returning device %p.\n", *device);
394
395     return D3D_OK;
396 }
397
398 static HRESULT WINAPI d3d8_indexbuffer_SetPrivateData(IDirect3DIndexBuffer8 *iface,
399         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
400 {
401     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
402     struct wined3d_resource *resource;
403     HRESULT hr;
404
405     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
406             iface, debugstr_guid(guid), data, data_size, flags);
407
408     wined3d_mutex_lock();
409     resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
410     hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
411     wined3d_mutex_unlock();
412
413     return hr;
414 }
415
416 static HRESULT WINAPI d3d8_indexbuffer_GetPrivateData(IDirect3DIndexBuffer8 *iface,
417         REFGUID guid, void *data, DWORD *data_size)
418 {
419     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
420     struct wined3d_resource *resource;
421     HRESULT hr;
422
423     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
424             iface, debugstr_guid(guid), data, data_size);
425
426     wined3d_mutex_lock();
427     resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
428     hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
429     wined3d_mutex_unlock();
430
431     return hr;
432 }
433
434 static HRESULT WINAPI d3d8_indexbuffer_FreePrivateData(IDirect3DIndexBuffer8 *iface, REFGUID guid)
435 {
436     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
437     struct wined3d_resource *resource;
438     HRESULT hr;
439
440     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
441
442     wined3d_mutex_lock();
443     resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
444     hr = wined3d_resource_free_private_data(resource, guid);
445     wined3d_mutex_unlock();
446
447     return hr;
448 }
449
450 static DWORD WINAPI d3d8_indexbuffer_SetPriority(IDirect3DIndexBuffer8 *iface, DWORD priority)
451 {
452     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
453     DWORD previous;
454
455     TRACE("iface %p, priority %u.\n", iface, priority);
456
457     wined3d_mutex_lock();
458     previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
459     wined3d_mutex_unlock();
460
461     return previous;
462 }
463
464 static DWORD WINAPI d3d8_indexbuffer_GetPriority(IDirect3DIndexBuffer8 *iface)
465 {
466     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
467     DWORD priority;
468
469     TRACE("iface %p.\n", iface);
470
471     wined3d_mutex_lock();
472     priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
473     wined3d_mutex_unlock();
474
475     return priority;
476 }
477
478 static void WINAPI d3d8_indexbuffer_PreLoad(IDirect3DIndexBuffer8 *iface)
479 {
480     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
481
482     TRACE("iface %p.\n", iface);
483
484     wined3d_mutex_lock();
485     wined3d_buffer_preload(buffer->wined3d_buffer);
486     wined3d_mutex_unlock();
487 }
488
489 static D3DRESOURCETYPE WINAPI d3d8_indexbuffer_GetType(IDirect3DIndexBuffer8 *iface)
490 {
491     TRACE("iface %p.\n", iface);
492
493     return D3DRTYPE_INDEXBUFFER;
494 }
495
496 static HRESULT WINAPI d3d8_indexbuffer_Lock(IDirect3DIndexBuffer8 *iface, UINT offset, UINT size,
497         BYTE **data, DWORD flags)
498 {
499     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
500     HRESULT hr;
501
502     TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
503             iface, offset, size, data, flags);
504
505     wined3d_mutex_lock();
506     hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, data, flags);
507     wined3d_mutex_unlock();
508
509     return hr;
510 }
511
512 static HRESULT WINAPI d3d8_indexbuffer_Unlock(IDirect3DIndexBuffer8 *iface)
513 {
514     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
515
516     TRACE("iface %p.\n", iface);
517
518     wined3d_mutex_lock();
519     wined3d_buffer_unmap(buffer->wined3d_buffer);
520     wined3d_mutex_unlock();
521
522     return D3D_OK;
523 }
524
525 static HRESULT WINAPI d3d8_indexbuffer_GetDesc(IDirect3DIndexBuffer8 *iface,
526         D3DINDEXBUFFER_DESC *desc)
527 {
528     struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
529     struct wined3d_resource_desc wined3d_desc;
530     struct wined3d_resource *wined3d_resource;
531
532     TRACE("iface %p, desc %p.\n", iface, desc);
533
534     wined3d_mutex_lock();
535     wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
536     wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
537     wined3d_mutex_unlock();
538
539     desc->Format = d3dformat_from_wined3dformat(buffer->format);
540     desc->Type = D3DRTYPE_INDEXBUFFER;
541     desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
542     desc->Pool = wined3d_desc.pool;
543     desc->Size = wined3d_desc.size;
544
545     return D3D_OK;
546 }
547
548 static const IDirect3DIndexBuffer8Vtbl d3d8_indexbuffer_vtbl =
549 {
550     /* IUnknown */
551     d3d8_indexbuffer_QueryInterface,
552     d3d8_indexbuffer_AddRef,
553     d3d8_indexbuffer_Release,
554     /* IDirect3DResource8 */
555     d3d8_indexbuffer_GetDevice,
556     d3d8_indexbuffer_SetPrivateData,
557     d3d8_indexbuffer_GetPrivateData,
558     d3d8_indexbuffer_FreePrivateData,
559     d3d8_indexbuffer_SetPriority,
560     d3d8_indexbuffer_GetPriority,
561     d3d8_indexbuffer_PreLoad,
562     d3d8_indexbuffer_GetType,
563     /* IDirect3DIndexBuffer8 */
564     d3d8_indexbuffer_Lock,
565     d3d8_indexbuffer_Unlock,
566     d3d8_indexbuffer_GetDesc,
567 };
568
569 static void STDMETHODCALLTYPE d3d8_indexbuffer_wined3d_object_destroyed(void *parent)
570 {
571     HeapFree(GetProcessHeap(), 0, parent);
572 }
573
574 static const struct wined3d_parent_ops d3d8_indexbuffer_wined3d_parent_ops =
575 {
576     d3d8_indexbuffer_wined3d_object_destroyed,
577 };
578
579 HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *device,
580         UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool)
581 {
582     HRESULT hr;
583
584     buffer->IDirect3DIndexBuffer8_iface.lpVtbl = &d3d8_indexbuffer_vtbl;
585     buffer->refcount = 1;
586     buffer->format = wined3dformat_from_d3dformat(format);
587
588     wined3d_mutex_lock();
589     hr = wined3d_buffer_create_ib(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
590             (enum wined3d_pool)pool, buffer, &d3d8_indexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
591     wined3d_mutex_unlock();
592     if (FAILED(hr))
593     {
594         WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
595         return hr;
596     }
597
598     buffer->parent_device = &device->IDirect3DDevice8_iface;
599     IDirect3DDevice8_AddRef(buffer->parent_device);
600
601     return D3D_OK;
602 }
603
604 struct d3d8_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface)
605 {
606     if (!iface)
607         return NULL;
608     assert(iface->lpVtbl == &d3d8_indexbuffer_vtbl);
609
610     return impl_from_IDirect3DIndexBuffer8(iface);
611 }