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