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