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