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