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