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