* Sync up to trunk HEAD (r62975).
[reactos.git] / dll / directx / wine / 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 "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 DWORD previous;
133
134 TRACE("iface %p, priority %u.\n", iface, priority);
135
136 wined3d_mutex_lock();
137 previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
138 wined3d_mutex_unlock();
139
140 return previous;
141 }
142
143 static DWORD WINAPI d3d9_vertexbuffer_GetPriority(IDirect3DVertexBuffer9 *iface)
144 {
145 struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
146 DWORD priority;
147
148 TRACE("iface %p.\n", iface);
149
150 wined3d_mutex_lock();
151 priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
152 wined3d_mutex_unlock();
153
154 return priority;
155 }
156
157 static void WINAPI d3d9_vertexbuffer_PreLoad(IDirect3DVertexBuffer9 *iface)
158 {
159 struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
160
161 TRACE("iface %p.\n", iface);
162
163 wined3d_mutex_lock();
164 wined3d_buffer_preload(buffer->wined3d_buffer);
165 wined3d_mutex_unlock();
166 }
167
168 static D3DRESOURCETYPE WINAPI d3d9_vertexbuffer_GetType(IDirect3DVertexBuffer9 *iface)
169 {
170 TRACE("iface %p.\n", iface);
171
172 return D3DRTYPE_VERTEXBUFFER;
173 }
174
175 static HRESULT WINAPI d3d9_vertexbuffer_Lock(IDirect3DVertexBuffer9 *iface, UINT offset, UINT size,
176 void **data, DWORD flags)
177 {
178 struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
179 HRESULT hr;
180
181 TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
182 iface, offset, size, data, flags);
183
184 wined3d_mutex_lock();
185 hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, (BYTE **)data, flags);
186 wined3d_mutex_unlock();
187
188 return hr;
189 }
190
191 static HRESULT WINAPI d3d9_vertexbuffer_Unlock(IDirect3DVertexBuffer9 *iface)
192 {
193 struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
194
195 TRACE("iface %p.\n", iface);
196
197 wined3d_mutex_lock();
198 wined3d_buffer_unmap(buffer->wined3d_buffer);
199 wined3d_mutex_unlock();
200
201 return D3D_OK;
202 }
203
204 static HRESULT WINAPI d3d9_vertexbuffer_GetDesc(IDirect3DVertexBuffer9 *iface,
205 D3DVERTEXBUFFER_DESC *desc)
206 {
207 struct d3d9_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer9(iface);
208 struct wined3d_resource_desc wined3d_desc;
209 struct wined3d_resource *wined3d_resource;
210
211 TRACE("iface %p, desc %p.\n", iface, desc);
212
213 wined3d_mutex_lock();
214 wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
215 wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
216 wined3d_mutex_unlock();
217
218 desc->Format = D3DFMT_VERTEXDATA;
219 desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
220 desc->Pool = wined3d_desc.pool;
221 desc->Size = wined3d_desc.size;
222 desc->Type = D3DRTYPE_VERTEXBUFFER;
223 desc->FVF = buffer->fvf;
224
225 return D3D_OK;
226 }
227
228 static const IDirect3DVertexBuffer9Vtbl d3d9_vertexbuffer_vtbl =
229 {
230 /* IUnknown */
231 d3d9_vertexbuffer_QueryInterface,
232 d3d9_vertexbuffer_AddRef,
233 d3d9_vertexbuffer_Release,
234 /* IDirect3DResource9 */
235 d3d9_vertexbuffer_GetDevice,
236 d3d9_vertexbuffer_SetPrivateData,
237 d3d9_vertexbuffer_GetPrivateData,
238 d3d9_vertexbuffer_FreePrivateData,
239 d3d9_vertexbuffer_SetPriority,
240 d3d9_vertexbuffer_GetPriority,
241 d3d9_vertexbuffer_PreLoad,
242 d3d9_vertexbuffer_GetType,
243 /* IDirect3DVertexBuffer9 */
244 d3d9_vertexbuffer_Lock,
245 d3d9_vertexbuffer_Unlock,
246 d3d9_vertexbuffer_GetDesc,
247 };
248
249 static void STDMETHODCALLTYPE d3d9_vertexbuffer_wined3d_object_destroyed(void *parent)
250 {
251 struct d3d9_vertexbuffer *buffer = parent;
252 d3d9_resource_cleanup(&buffer->resource);
253 HeapFree(GetProcessHeap(), 0, buffer);
254 }
255
256 static const struct wined3d_parent_ops d3d9_vertexbuffer_wined3d_parent_ops =
257 {
258 d3d9_vertexbuffer_wined3d_object_destroyed,
259 };
260
261 HRESULT vertexbuffer_init(struct d3d9_vertexbuffer *buffer, struct d3d9_device *device,
262 UINT size, UINT usage, DWORD fvf, D3DPOOL pool)
263 {
264 HRESULT hr;
265
266 buffer->IDirect3DVertexBuffer9_iface.lpVtbl = &d3d9_vertexbuffer_vtbl;
267 buffer->fvf = fvf;
268 d3d9_resource_init(&buffer->resource);
269
270 wined3d_mutex_lock();
271 hr = wined3d_buffer_create_vb(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
272 (enum wined3d_pool)pool, buffer, &d3d9_vertexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
273 wined3d_mutex_unlock();
274 if (FAILED(hr))
275 {
276 WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
277 return hr;
278 }
279
280 buffer->parent_device = &device->IDirect3DDevice9Ex_iface;
281 IDirect3DDevice9Ex_AddRef(buffer->parent_device);
282
283 return D3D_OK;
284 }
285
286 struct d3d9_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer9(IDirect3DVertexBuffer9 *iface)
287 {
288 if (!iface)
289 return NULL;
290 assert(iface->lpVtbl == &d3d9_vertexbuffer_vtbl);
291
292 return impl_from_IDirect3DVertexBuffer9(iface);
293 }
294
295 static inline struct d3d9_indexbuffer *impl_from_IDirect3DIndexBuffer9(IDirect3DIndexBuffer9 *iface)
296 {
297 return CONTAINING_RECORD(iface, struct d3d9_indexbuffer, IDirect3DIndexBuffer9_iface);
298 }
299
300 static HRESULT WINAPI d3d9_indexbuffer_QueryInterface(IDirect3DIndexBuffer9 *iface, REFIID riid, void **out)
301 {
302 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
303
304 if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer9)
305 || IsEqualGUID(riid, &IID_IDirect3DResource9)
306 || IsEqualGUID(riid, &IID_IUnknown))
307 {
308 IDirect3DIndexBuffer9_AddRef(iface);
309 *out = iface;
310 return S_OK;
311 }
312
313 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
314
315 *out = NULL;
316 return E_NOINTERFACE;
317 }
318
319 static ULONG WINAPI d3d9_indexbuffer_AddRef(IDirect3DIndexBuffer9 *iface)
320 {
321 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
322 ULONG refcount = InterlockedIncrement(&buffer->resource.refcount);
323
324 TRACE("%p increasing refcount to %u.\n", iface, refcount);
325
326 if (refcount == 1)
327 {
328 IDirect3DDevice9Ex_AddRef(buffer->parent_device);
329 wined3d_mutex_lock();
330 wined3d_buffer_incref(buffer->wined3d_buffer);
331 wined3d_mutex_unlock();
332 }
333
334 return refcount;
335 }
336
337 static ULONG WINAPI d3d9_indexbuffer_Release(IDirect3DIndexBuffer9 *iface)
338 {
339 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
340 ULONG refcount = InterlockedDecrement(&buffer->resource.refcount);
341
342 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
343
344 if (!refcount)
345 {
346 IDirect3DDevice9Ex *device = buffer->parent_device;
347
348 wined3d_mutex_lock();
349 wined3d_buffer_decref(buffer->wined3d_buffer);
350 wined3d_mutex_unlock();
351
352 /* Release the device last, as it may cause the device to be destroyed. */
353 IDirect3DDevice9Ex_Release(device);
354 }
355
356 return refcount;
357 }
358
359 static HRESULT WINAPI d3d9_indexbuffer_GetDevice(IDirect3DIndexBuffer9 *iface, IDirect3DDevice9 **device)
360 {
361 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
362
363 TRACE("iface %p, device %p.\n", iface, device);
364
365 *device = (IDirect3DDevice9 *)buffer->parent_device;
366 IDirect3DDevice9_AddRef(*device);
367
368 TRACE("Returning device %p.\n", *device);
369
370 return D3D_OK;
371 }
372
373 static HRESULT WINAPI d3d9_indexbuffer_SetPrivateData(IDirect3DIndexBuffer9 *iface,
374 REFGUID guid, const void *data, DWORD data_size, DWORD flags)
375 {
376 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
377 TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
378 iface, debugstr_guid(guid), data, data_size, flags);
379
380 return d3d9_resource_set_private_data(&buffer->resource, guid, data, data_size, flags);
381 }
382
383 static HRESULT WINAPI d3d9_indexbuffer_GetPrivateData(IDirect3DIndexBuffer9 *iface,
384 REFGUID guid, void *data, DWORD *data_size)
385 {
386 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
387 TRACE("iface %p, guid %s, data %p, data_size %p.\n",
388 iface, debugstr_guid(guid), data, data_size);
389
390 return d3d9_resource_get_private_data(&buffer->resource, guid, data, data_size);
391 }
392
393 static HRESULT WINAPI d3d9_indexbuffer_FreePrivateData(IDirect3DIndexBuffer9 *iface, REFGUID guid)
394 {
395 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
396 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
397
398 return d3d9_resource_free_private_data(&buffer->resource, guid);
399 }
400
401 static DWORD WINAPI d3d9_indexbuffer_SetPriority(IDirect3DIndexBuffer9 *iface, DWORD priority)
402 {
403 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
404 DWORD previous;
405
406 TRACE("iface %p, priority %u.\n", iface, priority);
407
408 wined3d_mutex_lock();
409 previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
410 wined3d_mutex_unlock();
411
412 return previous;
413 }
414
415 static DWORD WINAPI d3d9_indexbuffer_GetPriority(IDirect3DIndexBuffer9 *iface)
416 {
417 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
418 DWORD priority;
419
420 TRACE("iface %p.\n", iface);
421
422 wined3d_mutex_lock();
423 priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
424 wined3d_mutex_unlock();
425
426 return priority;
427 }
428
429 static void WINAPI d3d9_indexbuffer_PreLoad(IDirect3DIndexBuffer9 *iface)
430 {
431 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
432
433 TRACE("iface %p.\n", iface);
434
435 wined3d_mutex_lock();
436 wined3d_buffer_preload(buffer->wined3d_buffer);
437 wined3d_mutex_unlock();
438 }
439
440 static D3DRESOURCETYPE WINAPI d3d9_indexbuffer_GetType(IDirect3DIndexBuffer9 *iface)
441 {
442 TRACE("iface %p.\n", iface);
443
444 return D3DRTYPE_INDEXBUFFER;
445 }
446
447 static HRESULT WINAPI d3d9_indexbuffer_Lock(IDirect3DIndexBuffer9 *iface,
448 UINT offset, UINT size, void **data, DWORD flags)
449 {
450 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
451 HRESULT hr;
452
453 TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
454 iface, offset, size, data, flags);
455
456 wined3d_mutex_lock();
457 hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, (BYTE **)data, flags);
458 wined3d_mutex_unlock();
459
460 return hr;
461 }
462
463 static HRESULT WINAPI d3d9_indexbuffer_Unlock(IDirect3DIndexBuffer9 *iface)
464 {
465 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
466
467 TRACE("iface %p.\n", iface);
468
469 wined3d_mutex_lock();
470 wined3d_buffer_unmap(buffer->wined3d_buffer);
471 wined3d_mutex_unlock();
472
473 return D3D_OK;
474 }
475
476 static HRESULT WINAPI d3d9_indexbuffer_GetDesc(IDirect3DIndexBuffer9 *iface, D3DINDEXBUFFER_DESC *desc)
477 {
478 struct d3d9_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer9(iface);
479 struct wined3d_resource_desc wined3d_desc;
480 struct wined3d_resource *wined3d_resource;
481
482 TRACE("iface %p, desc %p.\n", iface, desc);
483
484 wined3d_mutex_lock();
485 wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
486 wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
487 wined3d_mutex_unlock();
488
489 desc->Format = d3dformat_from_wined3dformat(buffer->format);
490 desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
491 desc->Pool = wined3d_desc.pool;
492 desc->Size = wined3d_desc.size;
493 desc->Type = D3DRTYPE_INDEXBUFFER;
494
495 return D3D_OK;
496 }
497
498 static const IDirect3DIndexBuffer9Vtbl d3d9_indexbuffer_vtbl =
499 {
500 /* IUnknown */
501 d3d9_indexbuffer_QueryInterface,
502 d3d9_indexbuffer_AddRef,
503 d3d9_indexbuffer_Release,
504 /* IDirect3DResource9 */
505 d3d9_indexbuffer_GetDevice,
506 d3d9_indexbuffer_SetPrivateData,
507 d3d9_indexbuffer_GetPrivateData,
508 d3d9_indexbuffer_FreePrivateData,
509 d3d9_indexbuffer_SetPriority,
510 d3d9_indexbuffer_GetPriority,
511 d3d9_indexbuffer_PreLoad,
512 d3d9_indexbuffer_GetType,
513 /* IDirect3DIndexBuffer9 */
514 d3d9_indexbuffer_Lock,
515 d3d9_indexbuffer_Unlock,
516 d3d9_indexbuffer_GetDesc,
517 };
518
519 static void STDMETHODCALLTYPE d3d9_indexbuffer_wined3d_object_destroyed(void *parent)
520 {
521 struct d3d9_indexbuffer *buffer = parent;
522 d3d9_resource_cleanup(&buffer->resource);
523 HeapFree(GetProcessHeap(), 0, buffer);
524 }
525
526 static const struct wined3d_parent_ops d3d9_indexbuffer_wined3d_parent_ops =
527 {
528 d3d9_indexbuffer_wined3d_object_destroyed,
529 };
530
531 HRESULT indexbuffer_init(struct d3d9_indexbuffer *buffer, struct d3d9_device *device,
532 UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool)
533 {
534 HRESULT hr;
535
536 buffer->IDirect3DIndexBuffer9_iface.lpVtbl = &d3d9_indexbuffer_vtbl;
537 buffer->format = wined3dformat_from_d3dformat(format);
538 d3d9_resource_init(&buffer->resource);
539
540 wined3d_mutex_lock();
541 hr = wined3d_buffer_create_ib(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
542 (enum wined3d_pool)pool, buffer, &d3d9_indexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
543 wined3d_mutex_unlock();
544 if (FAILED(hr))
545 {
546 WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
547 return hr;
548 }
549
550 buffer->parent_device = &device->IDirect3DDevice9Ex_iface;
551 IDirect3DDevice9Ex_AddRef(buffer->parent_device);
552
553 return D3D_OK;
554 }
555
556 struct d3d9_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer9(IDirect3DIndexBuffer9 *iface)
557 {
558 if (!iface)
559 return NULL;
560 assert(iface->lpVtbl == &d3d9_indexbuffer_vtbl);
561
562 return impl_from_IDirect3DIndexBuffer9(iface);
563 }