d3d8: Don't print the ResourceManagerDiscardBytes fixme when Bytes == 0.
[wine] / dlls / 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 "config.h"
20 #include "d3d8_private.h"
21
22 WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
23
24 static inline IDirect3DVertexBuffer8Impl *impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface)
25 {
26     return CONTAINING_RECORD(iface, IDirect3DVertexBuffer8Impl, lpVtbl);
27 }
28
29 static HRESULT WINAPI d3d8_vertexbuffer_QueryInterface(IDirect3DVertexBuffer8 *iface, REFIID riid, void **object)
30 {
31     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
32
33     if (IsEqualGUID(riid, &IID_IDirect3DVertexBuffer8)
34             || IsEqualGUID(riid, &IID_IDirect3DResource8)
35             || IsEqualGUID(riid, &IID_IUnknown))
36     {
37         IUnknown_AddRef(iface);
38         *object = iface;
39         return S_OK;
40     }
41
42     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
43
44     *object = NULL;
45     return E_NOINTERFACE;
46 }
47
48 static ULONG WINAPI d3d8_vertexbuffer_AddRef(IDirect3DVertexBuffer8 *iface)
49 {
50     IDirect3DVertexBuffer8Impl *buffer = (IDirect3DVertexBuffer8Impl *)iface;
51     ULONG refcount = InterlockedIncrement(&buffer->ref);
52
53     TRACE("%p increasing refcount to %u.\n", iface, refcount);
54
55     if (refcount == 1)
56     {
57         IDirect3DDevice8_AddRef(buffer->parentDevice);
58         wined3d_mutex_lock();
59         wined3d_buffer_incref(buffer->wineD3DVertexBuffer);
60         wined3d_mutex_unlock();
61     }
62
63     return refcount;
64 }
65
66 static ULONG WINAPI d3d8_vertexbuffer_Release(IDirect3DVertexBuffer8 *iface)
67 {
68     IDirect3DVertexBuffer8Impl *buffer = (IDirect3DVertexBuffer8Impl *)iface;
69     ULONG refcount = InterlockedDecrement(&buffer->ref);
70
71     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
72
73     if (!refcount)
74     {
75         IDirect3DDevice8 *device = buffer->parentDevice;
76
77         wined3d_mutex_lock();
78         wined3d_buffer_decref(buffer->wineD3DVertexBuffer);
79         wined3d_mutex_unlock();
80
81         /* Release the device last, as it may cause the device to be destroyed. */
82         IDirect3DDevice8_Release(device);
83     }
84
85     return refcount;
86 }
87
88 static HRESULT WINAPI d3d8_vertexbuffer_GetDevice(IDirect3DVertexBuffer8 *iface, IDirect3DDevice8 **device)
89 {
90     TRACE("iface %p, device %p.\n", iface, device);
91
92     *device = (IDirect3DDevice8 *)((IDirect3DVertexBuffer8Impl *)iface)->parentDevice;
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     IDirect3DVertexBuffer8Impl *buffer = impl_from_IDirect3DVertexBuffer8(iface);
104     struct wined3d_resource *resource;
105     HRESULT hr;
106
107     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
108             iface, debugstr_guid(guid), data, data_size, flags);
109
110     wined3d_mutex_lock();
111     resource = wined3d_buffer_get_resource(buffer->wineD3DVertexBuffer);
112     hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
113     wined3d_mutex_unlock();
114
115     return hr;
116 }
117
118 static HRESULT WINAPI d3d8_vertexbuffer_GetPrivateData(IDirect3DVertexBuffer8 *iface,
119         REFGUID guid, void *data, DWORD *data_size)
120 {
121     IDirect3DVertexBuffer8Impl *buffer = impl_from_IDirect3DVertexBuffer8(iface);
122     struct wined3d_resource *resource;
123     HRESULT hr;
124
125     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
126             iface, debugstr_guid(guid), data, data_size);
127
128     wined3d_mutex_lock();
129     resource = wined3d_buffer_get_resource(buffer->wineD3DVertexBuffer);
130     hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
131     wined3d_mutex_unlock();
132
133     return hr;
134 }
135
136 static HRESULT WINAPI d3d8_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer8 *iface, REFGUID guid)
137 {
138     IDirect3DVertexBuffer8Impl *buffer = impl_from_IDirect3DVertexBuffer8(iface);
139     struct wined3d_resource *resource;
140     HRESULT hr;
141
142     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
143
144     wined3d_mutex_lock();
145     resource = wined3d_buffer_get_resource(buffer->wineD3DVertexBuffer);
146     hr = wined3d_resource_free_private_data(resource, guid);
147     wined3d_mutex_unlock();
148
149     return hr;
150 }
151
152 static DWORD WINAPI d3d8_vertexbuffer_SetPriority(IDirect3DVertexBuffer8 *iface, DWORD priority)
153 {
154     DWORD previous;
155
156     TRACE("iface %p, priority %u.\n", iface, priority);
157
158     wined3d_mutex_lock();
159     previous = wined3d_buffer_set_priority(((IDirect3DVertexBuffer8Impl *)iface)->wineD3DVertexBuffer, priority);
160     wined3d_mutex_unlock();
161
162     return previous;
163 }
164
165 static DWORD WINAPI d3d8_vertexbuffer_GetPriority(IDirect3DVertexBuffer8 *iface)
166 {
167     DWORD priority;
168
169     TRACE("iface %p.\n", iface);
170
171     wined3d_mutex_lock();
172     priority = wined3d_buffer_get_priority(((IDirect3DVertexBuffer8Impl *)iface)->wineD3DVertexBuffer);
173     wined3d_mutex_unlock();
174
175     return priority;
176 }
177
178 static void WINAPI d3d8_vertexbuffer_PreLoad(IDirect3DVertexBuffer8 *iface)
179 {
180     TRACE("iface %p.\n", iface);
181
182     wined3d_mutex_lock();
183     wined3d_buffer_preload(((IDirect3DVertexBuffer8Impl *)iface)->wineD3DVertexBuffer);
184     wined3d_mutex_unlock();
185 }
186
187 static D3DRESOURCETYPE WINAPI d3d8_vertexbuffer_GetType(IDirect3DVertexBuffer8 *iface)
188 {
189     TRACE("iface %p.\n", iface);
190
191     return D3DRTYPE_VERTEXBUFFER;
192 }
193
194 static HRESULT WINAPI d3d8_vertexbuffer_Lock(IDirect3DVertexBuffer8 *iface,
195         UINT offset, UINT size, BYTE **data, DWORD flags)
196 {
197     HRESULT hr;
198
199     TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
200             iface, offset, size, data, flags);
201
202     wined3d_mutex_lock();
203     hr = wined3d_buffer_map(((IDirect3DVertexBuffer8Impl *)iface)->wineD3DVertexBuffer,
204             offset, size, data, flags);
205     wined3d_mutex_unlock();
206
207     return hr;
208 }
209
210 static HRESULT WINAPI d3d8_vertexbuffer_Unlock(IDirect3DVertexBuffer8 *iface)
211 {
212     TRACE("iface %p.\n", iface);
213
214     wined3d_mutex_lock();
215     wined3d_buffer_unmap(((IDirect3DVertexBuffer8Impl *)iface)->wineD3DVertexBuffer);
216     wined3d_mutex_unlock();
217
218     return D3D_OK;
219 }
220
221 static HRESULT WINAPI d3d8_vertexbuffer_GetDesc(IDirect3DVertexBuffer8 *iface, D3DVERTEXBUFFER_DESC *desc)
222 {
223     IDirect3DVertexBuffer8Impl *buffer = (IDirect3DVertexBuffer8Impl *)iface;
224     struct wined3d_resource_desc wined3d_desc;
225     struct wined3d_resource *wined3d_resource;
226
227     TRACE("iface %p, desc %p.\n", iface, desc);
228
229     wined3d_mutex_lock();
230     wined3d_resource = wined3d_buffer_get_resource(buffer->wineD3DVertexBuffer);
231     wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
232     wined3d_mutex_unlock();
233
234     desc->Type = D3DRTYPE_VERTEXBUFFER;
235     desc->Usage = wined3d_desc.usage;
236     desc->Pool = wined3d_desc.pool;
237     desc->Size = wined3d_desc.size;
238     desc->FVF = buffer->fvf;
239     desc->Format = D3DFMT_VERTEXDATA;
240
241     return D3D_OK;
242 }
243
244 static const IDirect3DVertexBuffer8Vtbl Direct3DVertexBuffer8_Vtbl =
245 {
246     /* IUnknown */
247     d3d8_vertexbuffer_QueryInterface,
248     d3d8_vertexbuffer_AddRef,
249     d3d8_vertexbuffer_Release,
250     /* IDirect3DResource8 */
251     d3d8_vertexbuffer_GetDevice,
252     d3d8_vertexbuffer_SetPrivateData,
253     d3d8_vertexbuffer_GetPrivateData,
254     d3d8_vertexbuffer_FreePrivateData,
255     d3d8_vertexbuffer_SetPriority,
256     d3d8_vertexbuffer_GetPriority,
257     d3d8_vertexbuffer_PreLoad,
258     d3d8_vertexbuffer_GetType,
259     /* IDirect3DVertexBuffer8 */
260     d3d8_vertexbuffer_Lock,
261     d3d8_vertexbuffer_Unlock,
262     d3d8_vertexbuffer_GetDesc,
263 };
264
265 static void STDMETHODCALLTYPE d3d8_vertexbuffer_wined3d_object_destroyed(void *parent)
266 {
267     HeapFree(GetProcessHeap(), 0, parent);
268 }
269
270 static const struct wined3d_parent_ops d3d8_vertexbuffer_wined3d_parent_ops =
271 {
272     d3d8_vertexbuffer_wined3d_object_destroyed,
273 };
274
275 HRESULT vertexbuffer_init(IDirect3DVertexBuffer8Impl *buffer, IDirect3DDevice8Impl *device,
276         UINT size, DWORD usage, DWORD fvf, D3DPOOL pool)
277 {
278     HRESULT hr;
279
280     buffer->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
281     buffer->ref = 1;
282     buffer->fvf = fvf;
283
284     wined3d_mutex_lock();
285     hr = wined3d_buffer_create_vb(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
286             (WINED3DPOOL)pool, buffer, &d3d8_vertexbuffer_wined3d_parent_ops, &buffer->wineD3DVertexBuffer);
287     wined3d_mutex_unlock();
288     if (FAILED(hr))
289     {
290         WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
291         return hr;
292     }
293
294     buffer->parentDevice = &device->IDirect3DDevice8_iface;
295     IUnknown_AddRef(buffer->parentDevice);
296
297     return D3D_OK;
298 }
299
300 static inline IDirect3DIndexBuffer8Impl *impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface)
301 {
302     return CONTAINING_RECORD(iface, IDirect3DIndexBuffer8Impl, lpVtbl);
303 }
304
305 static HRESULT WINAPI d3d8_indexbuffer_QueryInterface(IDirect3DIndexBuffer8 *iface, REFIID riid, void **object)
306 {
307     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
308
309     if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer8)
310             || IsEqualGUID(riid, &IID_IDirect3DResource8)
311             || IsEqualGUID(riid, &IID_IUnknown))
312     {
313         IUnknown_AddRef(iface);
314         *object = iface;
315         return S_OK;
316     }
317
318     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
319
320     *object = NULL;
321     return E_NOINTERFACE;
322 }
323
324 static ULONG WINAPI d3d8_indexbuffer_AddRef(IDirect3DIndexBuffer8 *iface)
325 {
326     IDirect3DIndexBuffer8Impl *buffer = (IDirect3DIndexBuffer8Impl *)iface;
327     ULONG refcount = InterlockedIncrement(&buffer->ref);
328
329     TRACE("%p increasing refcount to %u.\n", iface, refcount);
330
331     if (refcount == 1)
332     {
333         IDirect3DDevice8_AddRef(buffer->parentDevice);
334         wined3d_mutex_lock();
335         wined3d_buffer_incref(buffer->wineD3DIndexBuffer);
336         wined3d_mutex_unlock();
337     }
338
339     return refcount;
340 }
341
342 static ULONG WINAPI d3d8_indexbuffer_Release(IDirect3DIndexBuffer8 *iface)
343 {
344     IDirect3DIndexBuffer8Impl *buffer = (IDirect3DIndexBuffer8Impl *)iface;
345     ULONG refcount = InterlockedDecrement(&buffer->ref);
346
347     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
348
349     if (!refcount)
350     {
351         IDirect3DDevice8 *device = buffer->parentDevice;
352
353         wined3d_mutex_lock();
354         wined3d_buffer_decref(buffer->wineD3DIndexBuffer);
355         wined3d_mutex_unlock();
356
357         /* Release the device last, as it may cause the device to be destroyed. */
358         IDirect3DDevice8_Release(device);
359     }
360
361     return refcount;
362 }
363
364 static HRESULT WINAPI d3d8_indexbuffer_GetDevice(IDirect3DIndexBuffer8 *iface, IDirect3DDevice8 **device)
365 {
366     TRACE("iface %p, device %p.\n", iface, device);
367
368     *device = (IDirect3DDevice8 *)((IDirect3DIndexBuffer8Impl *)iface)->parentDevice;
369     IDirect3DDevice8_AddRef(*device);
370
371     TRACE("Returning device %p.\n", *device);
372
373     return D3D_OK;
374 }
375
376 static HRESULT WINAPI d3d8_indexbuffer_SetPrivateData(IDirect3DIndexBuffer8 *iface,
377         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
378 {
379     IDirect3DIndexBuffer8Impl *buffer = impl_from_IDirect3DIndexBuffer8(iface);
380     struct wined3d_resource *resource;
381     HRESULT hr;
382
383     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
384             iface, debugstr_guid(guid), data, data_size, flags);
385
386     wined3d_mutex_lock();
387     resource = wined3d_buffer_get_resource(buffer->wineD3DIndexBuffer);
388     hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags);
389     wined3d_mutex_unlock();
390
391     return hr;
392 }
393
394 static HRESULT WINAPI d3d8_indexbuffer_GetPrivateData(IDirect3DIndexBuffer8 *iface,
395         REFGUID guid, void *data, DWORD *data_size)
396 {
397     IDirect3DIndexBuffer8Impl *buffer = impl_from_IDirect3DIndexBuffer8(iface);
398     struct wined3d_resource *resource;
399     HRESULT hr;
400
401     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
402             iface, debugstr_guid(guid), data, data_size);
403
404     wined3d_mutex_lock();
405     resource = wined3d_buffer_get_resource(buffer->wineD3DIndexBuffer);
406     hr = wined3d_resource_get_private_data(resource, guid, data, data_size);
407     wined3d_mutex_unlock();
408
409     return hr;
410 }
411
412 static HRESULT WINAPI d3d8_indexbuffer_FreePrivateData(IDirect3DIndexBuffer8 *iface, REFGUID guid)
413 {
414     IDirect3DIndexBuffer8Impl *buffer = impl_from_IDirect3DIndexBuffer8(iface);
415     struct wined3d_resource *resource;
416     HRESULT hr;
417
418     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
419
420     wined3d_mutex_lock();
421     resource = wined3d_buffer_get_resource(buffer->wineD3DIndexBuffer);
422     hr = wined3d_resource_free_private_data(resource, guid);
423     wined3d_mutex_unlock();
424
425     return hr;
426 }
427
428 static DWORD WINAPI d3d8_indexbuffer_SetPriority(IDirect3DIndexBuffer8 *iface, DWORD priority)
429 {
430     DWORD previous;
431
432     TRACE("iface %p, priority %u.\n", iface, priority);
433
434     wined3d_mutex_lock();
435     previous = wined3d_buffer_set_priority(((IDirect3DIndexBuffer8Impl *)iface)->wineD3DIndexBuffer, priority);
436     wined3d_mutex_unlock();
437
438     return previous;
439 }
440
441 static DWORD WINAPI d3d8_indexbuffer_GetPriority(IDirect3DIndexBuffer8 *iface)
442 {
443     DWORD priority;
444
445     TRACE("iface %p.\n", iface);
446
447     wined3d_mutex_lock();
448     priority = wined3d_buffer_get_priority(((IDirect3DIndexBuffer8Impl *)iface)->wineD3DIndexBuffer);
449     wined3d_mutex_unlock();
450
451     return priority;
452 }
453
454 static void WINAPI d3d8_indexbuffer_PreLoad(IDirect3DIndexBuffer8 *iface)
455 {
456     TRACE("iface %p.\n", iface);
457
458     wined3d_mutex_lock();
459     wined3d_buffer_preload(((IDirect3DIndexBuffer8Impl *)iface)->wineD3DIndexBuffer);
460     wined3d_mutex_unlock();
461 }
462
463 static D3DRESOURCETYPE WINAPI d3d8_indexbuffer_GetType(IDirect3DIndexBuffer8 *iface)
464 {
465     TRACE("iface %p.\n", iface);
466
467     return D3DRTYPE_INDEXBUFFER;
468 }
469
470 static HRESULT WINAPI d3d8_indexbuffer_Lock(IDirect3DIndexBuffer8 *iface,
471         UINT offset, UINT size, BYTE **data, DWORD flags)
472 {
473     HRESULT hr;
474
475     TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
476             iface, offset, size, data, flags);
477
478     wined3d_mutex_lock();
479     hr = wined3d_buffer_map(((IDirect3DIndexBuffer8Impl *)iface)->wineD3DIndexBuffer,
480             offset, size, data, flags);
481     wined3d_mutex_unlock();
482
483     return hr;
484 }
485
486 static HRESULT WINAPI d3d8_indexbuffer_Unlock(IDirect3DIndexBuffer8 *iface)
487 {
488     TRACE("iface %p.\n", iface);
489
490     wined3d_mutex_lock();
491     wined3d_buffer_unmap(((IDirect3DIndexBuffer8Impl *)iface)->wineD3DIndexBuffer);
492     wined3d_mutex_unlock();
493
494     return D3D_OK;
495 }
496
497 static HRESULT WINAPI d3d8_indexbuffer_GetDesc(IDirect3DIndexBuffer8 *iface, D3DINDEXBUFFER_DESC *desc)
498 {
499     IDirect3DIndexBuffer8Impl *buffer = (IDirect3DIndexBuffer8Impl *)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->wineD3DIndexBuffer);
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;
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     HeapFree(GetProcessHeap(), 0, parent);
543 }
544
545 static const struct wined3d_parent_ops d3d8_indexbuffer_wined3d_parent_ops =
546 {
547     d3d8_indexbuffer_wined3d_object_destroyed,
548 };
549
550 HRESULT indexbuffer_init(IDirect3DIndexBuffer8Impl *buffer, IDirect3DDevice8Impl *device,
551         UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool)
552 {
553     HRESULT hr;
554
555     buffer->lpVtbl = &d3d8_indexbuffer_vtbl;
556     buffer->ref = 1;
557     buffer->format = wined3dformat_from_d3dformat(format);
558
559     wined3d_mutex_lock();
560     hr = wined3d_buffer_create_ib(device->wined3d_device, size, usage & WINED3DUSAGE_MASK,
561             (WINED3DPOOL)pool, buffer, &d3d8_indexbuffer_wined3d_parent_ops, &buffer->wineD3DIndexBuffer);
562     wined3d_mutex_unlock();
563     if (FAILED(hr))
564     {
565         WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
566         return hr;
567     }
568
569     buffer->parentDevice = &device->IDirect3DDevice8_iface;
570     IUnknown_AddRef(buffer->parentDevice);
571
572     return D3D_OK;
573 }