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