* Sync up to trunk HEAD (r62975).
[reactos.git] / dll / directx / wine / d3d8 / buffer.c
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 DWORD previous;
132
133 TRACE("iface %p, priority %u.\n", iface, priority);
134
135 wined3d_mutex_lock();
136 previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority);
137 wined3d_mutex_unlock();
138
139 return previous;
140 }
141
142 static DWORD WINAPI d3d8_vertexbuffer_GetPriority(IDirect3DVertexBuffer8 *iface)
143 {
144 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
145 DWORD priority;
146
147 TRACE("iface %p.\n", iface);
148
149 wined3d_mutex_lock();
150 priority = wined3d_buffer_get_priority(buffer->wined3d_buffer);
151 wined3d_mutex_unlock();
152
153 return priority;
154 }
155
156 static void WINAPI d3d8_vertexbuffer_PreLoad(IDirect3DVertexBuffer8 *iface)
157 {
158 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
159
160 TRACE("iface %p.\n", iface);
161
162 wined3d_mutex_lock();
163 wined3d_buffer_preload(buffer->wined3d_buffer);
164 wined3d_mutex_unlock();
165 }
166
167 static D3DRESOURCETYPE WINAPI d3d8_vertexbuffer_GetType(IDirect3DVertexBuffer8 *iface)
168 {
169 TRACE("iface %p.\n", iface);
170
171 return D3DRTYPE_VERTEXBUFFER;
172 }
173
174 static HRESULT WINAPI d3d8_vertexbuffer_Lock(IDirect3DVertexBuffer8 *iface, UINT offset, UINT size,
175 BYTE **data, DWORD flags)
176 {
177 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
178 HRESULT hr;
179
180 TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
181 iface, offset, size, data, flags);
182
183 wined3d_mutex_lock();
184 hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, data, flags);
185 wined3d_mutex_unlock();
186
187 return hr;
188 }
189
190 static HRESULT WINAPI d3d8_vertexbuffer_Unlock(IDirect3DVertexBuffer8 *iface)
191 {
192 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
193
194 TRACE("iface %p.\n", iface);
195
196 wined3d_mutex_lock();
197 wined3d_buffer_unmap(buffer->wined3d_buffer);
198 wined3d_mutex_unlock();
199
200 return D3D_OK;
201 }
202
203 static HRESULT WINAPI d3d8_vertexbuffer_GetDesc(IDirect3DVertexBuffer8 *iface,
204 D3DVERTEXBUFFER_DESC *desc)
205 {
206 struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface);
207 struct wined3d_resource_desc wined3d_desc;
208 struct wined3d_resource *wined3d_resource;
209
210 TRACE("iface %p, desc %p.\n", iface, desc);
211
212 wined3d_mutex_lock();
213 wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
214 wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
215 wined3d_mutex_unlock();
216
217 desc->Type = D3DRTYPE_VERTEXBUFFER;
218 desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
219 desc->Pool = wined3d_desc.pool;
220 desc->Size = wined3d_desc.size;
221 desc->FVF = buffer->fvf;
222 desc->Format = D3DFMT_VERTEXDATA;
223
224 return D3D_OK;
225 }
226
227 static const IDirect3DVertexBuffer8Vtbl Direct3DVertexBuffer8_Vtbl =
228 {
229 /* IUnknown */
230 d3d8_vertexbuffer_QueryInterface,
231 d3d8_vertexbuffer_AddRef,
232 d3d8_vertexbuffer_Release,
233 /* IDirect3DResource8 */
234 d3d8_vertexbuffer_GetDevice,
235 d3d8_vertexbuffer_SetPrivateData,
236 d3d8_vertexbuffer_GetPrivateData,
237 d3d8_vertexbuffer_FreePrivateData,
238 d3d8_vertexbuffer_SetPriority,
239 d3d8_vertexbuffer_GetPriority,
240 d3d8_vertexbuffer_PreLoad,
241 d3d8_vertexbuffer_GetType,
242 /* IDirect3DVertexBuffer8 */
243 d3d8_vertexbuffer_Lock,
244 d3d8_vertexbuffer_Unlock,
245 d3d8_vertexbuffer_GetDesc,
246 };
247
248 static void STDMETHODCALLTYPE d3d8_vertexbuffer_wined3d_object_destroyed(void *parent)
249 {
250 struct d3d8_vertexbuffer *buffer = parent;
251 d3d8_resource_cleanup(&buffer->resource);
252 HeapFree(GetProcessHeap(), 0, buffer);
253 }
254
255 static const struct wined3d_parent_ops d3d8_vertexbuffer_wined3d_parent_ops =
256 {
257 d3d8_vertexbuffer_wined3d_object_destroyed,
258 };
259
260 HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *device,
261 UINT size, DWORD usage, DWORD fvf, D3DPOOL pool)
262 {
263 HRESULT hr;
264
265 buffer->IDirect3DVertexBuffer8_iface.lpVtbl = &Direct3DVertexBuffer8_Vtbl;
266 d3d8_resource_init(&buffer->resource);
267 buffer->fvf = fvf;
268
269 wined3d_mutex_lock();
270 hr = wined3d_buffer_create_vb(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
271 (enum wined3d_pool)pool, buffer, &d3d8_vertexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
272 wined3d_mutex_unlock();
273 if (FAILED(hr))
274 {
275 WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
276 return hr;
277 }
278
279 buffer->parent_device = &device->IDirect3DDevice8_iface;
280 IDirect3DDevice8_AddRef(buffer->parent_device);
281
282 return D3D_OK;
283 }
284
285 struct d3d8_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface)
286 {
287 if (!iface)
288 return NULL;
289 assert(iface->lpVtbl == &Direct3DVertexBuffer8_Vtbl);
290
291 return impl_from_IDirect3DVertexBuffer8(iface);
292 }
293
294 static inline struct d3d8_indexbuffer *impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface)
295 {
296 return CONTAINING_RECORD(iface, struct d3d8_indexbuffer, IDirect3DIndexBuffer8_iface);
297 }
298
299 static HRESULT WINAPI d3d8_indexbuffer_QueryInterface(IDirect3DIndexBuffer8 *iface, REFIID riid, void **object)
300 {
301 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
302
303 if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer8)
304 || IsEqualGUID(riid, &IID_IDirect3DResource8)
305 || IsEqualGUID(riid, &IID_IUnknown))
306 {
307 IDirect3DIndexBuffer8_AddRef(iface);
308 *object = iface;
309 return S_OK;
310 }
311
312 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
313
314 *object = NULL;
315 return E_NOINTERFACE;
316 }
317
318 static ULONG WINAPI d3d8_indexbuffer_AddRef(IDirect3DIndexBuffer8 *iface)
319 {
320 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
321 ULONG refcount = InterlockedIncrement(&buffer->resource.refcount);
322
323 TRACE("%p increasing refcount to %u.\n", iface, refcount);
324
325 if (refcount == 1)
326 {
327 IDirect3DDevice8_AddRef(buffer->parent_device);
328 wined3d_mutex_lock();
329 wined3d_buffer_incref(buffer->wined3d_buffer);
330 wined3d_mutex_unlock();
331 }
332
333 return refcount;
334 }
335
336 static ULONG WINAPI d3d8_indexbuffer_Release(IDirect3DIndexBuffer8 *iface)
337 {
338 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
339 ULONG refcount = InterlockedDecrement(&buffer->resource.refcount);
340
341 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
342
343 if (!refcount)
344 {
345 IDirect3DDevice8 *device = buffer->parent_device;
346
347 wined3d_mutex_lock();
348 wined3d_buffer_decref(buffer->wined3d_buffer);
349 wined3d_mutex_unlock();
350
351 /* Release the device last, as it may cause the device to be destroyed. */
352 IDirect3DDevice8_Release(device);
353 }
354
355 return refcount;
356 }
357
358 static HRESULT WINAPI d3d8_indexbuffer_GetDevice(IDirect3DIndexBuffer8 *iface,
359 IDirect3DDevice8 **device)
360 {
361 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
362
363 TRACE("iface %p, device %p.\n", iface, device);
364
365 *device = buffer->parent_device;
366 IDirect3DDevice8_AddRef(*device);
367
368 TRACE("Returning device %p.\n", *device);
369
370 return D3D_OK;
371 }
372
373 static HRESULT WINAPI d3d8_indexbuffer_SetPrivateData(IDirect3DIndexBuffer8 *iface,
374 REFGUID guid, const void *data, DWORD data_size, DWORD flags)
375 {
376 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(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 d3d8_resource_set_private_data(&buffer->resource, guid, data, data_size, flags);
381 }
382
383 static HRESULT WINAPI d3d8_indexbuffer_GetPrivateData(IDirect3DIndexBuffer8 *iface,
384 REFGUID guid, void *data, DWORD *data_size)
385 {
386 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
387 TRACE("iface %p, guid %s, data %p, data_size %p.\n",
388 iface, debugstr_guid(guid), data, data_size);
389
390 return d3d8_resource_get_private_data(&buffer->resource, guid, data, data_size);
391 }
392
393 static HRESULT WINAPI d3d8_indexbuffer_FreePrivateData(IDirect3DIndexBuffer8 *iface, REFGUID guid)
394 {
395 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
396 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
397
398 return d3d8_resource_free_private_data(&buffer->resource, guid);
399 }
400
401 static DWORD WINAPI d3d8_indexbuffer_SetPriority(IDirect3DIndexBuffer8 *iface, DWORD priority)
402 {
403 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(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 d3d8_indexbuffer_GetPriority(IDirect3DIndexBuffer8 *iface)
416 {
417 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(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 d3d8_indexbuffer_PreLoad(IDirect3DIndexBuffer8 *iface)
430 {
431 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(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 d3d8_indexbuffer_GetType(IDirect3DIndexBuffer8 *iface)
441 {
442 TRACE("iface %p.\n", iface);
443
444 return D3DRTYPE_INDEXBUFFER;
445 }
446
447 static HRESULT WINAPI d3d8_indexbuffer_Lock(IDirect3DIndexBuffer8 *iface, UINT offset, UINT size,
448 BYTE **data, DWORD flags)
449 {
450 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(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, data, flags);
458 wined3d_mutex_unlock();
459
460 return hr;
461 }
462
463 static HRESULT WINAPI d3d8_indexbuffer_Unlock(IDirect3DIndexBuffer8 *iface)
464 {
465 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(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 d3d8_indexbuffer_GetDesc(IDirect3DIndexBuffer8 *iface,
477 D3DINDEXBUFFER_DESC *desc)
478 {
479 struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface);
480 struct wined3d_resource_desc wined3d_desc;
481 struct wined3d_resource *wined3d_resource;
482
483 TRACE("iface %p, desc %p.\n", iface, desc);
484
485 wined3d_mutex_lock();
486 wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
487 wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
488 wined3d_mutex_unlock();
489
490 desc->Format = d3dformat_from_wined3dformat(buffer->format);
491 desc->Type = D3DRTYPE_INDEXBUFFER;
492 desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK;
493 desc->Pool = wined3d_desc.pool;
494 desc->Size = wined3d_desc.size;
495
496 return D3D_OK;
497 }
498
499 static const IDirect3DIndexBuffer8Vtbl d3d8_indexbuffer_vtbl =
500 {
501 /* IUnknown */
502 d3d8_indexbuffer_QueryInterface,
503 d3d8_indexbuffer_AddRef,
504 d3d8_indexbuffer_Release,
505 /* IDirect3DResource8 */
506 d3d8_indexbuffer_GetDevice,
507 d3d8_indexbuffer_SetPrivateData,
508 d3d8_indexbuffer_GetPrivateData,
509 d3d8_indexbuffer_FreePrivateData,
510 d3d8_indexbuffer_SetPriority,
511 d3d8_indexbuffer_GetPriority,
512 d3d8_indexbuffer_PreLoad,
513 d3d8_indexbuffer_GetType,
514 /* IDirect3DIndexBuffer8 */
515 d3d8_indexbuffer_Lock,
516 d3d8_indexbuffer_Unlock,
517 d3d8_indexbuffer_GetDesc,
518 };
519
520 static void STDMETHODCALLTYPE d3d8_indexbuffer_wined3d_object_destroyed(void *parent)
521 {
522 struct d3d8_indexbuffer *buffer = parent;
523 d3d8_resource_cleanup(&buffer->resource);
524 HeapFree(GetProcessHeap(), 0, buffer);
525 }
526
527 static const struct wined3d_parent_ops d3d8_indexbuffer_wined3d_parent_ops =
528 {
529 d3d8_indexbuffer_wined3d_object_destroyed,
530 };
531
532 HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *device,
533 UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool)
534 {
535 HRESULT hr;
536
537 buffer->IDirect3DIndexBuffer8_iface.lpVtbl = &d3d8_indexbuffer_vtbl;
538 d3d8_resource_init(&buffer->resource);
539 buffer->format = wined3dformat_from_d3dformat(format);
540
541 wined3d_mutex_lock();
542 hr = wined3d_buffer_create_ib(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
543 (enum wined3d_pool)pool, buffer, &d3d8_indexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
544 wined3d_mutex_unlock();
545 if (FAILED(hr))
546 {
547 WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
548 return hr;
549 }
550
551 buffer->parent_device = &device->IDirect3DDevice8_iface;
552 IDirect3DDevice8_AddRef(buffer->parent_device);
553
554 return D3D_OK;
555 }
556
557 struct d3d8_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface)
558 {
559 if (!iface)
560 return NULL;
561 assert(iface->lpVtbl == &d3d8_indexbuffer_vtbl);
562
563 return impl_from_IDirect3DIndexBuffer8(iface);
564 }