msvcrt: Implemented _ltoa_s.
[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 HRESULT WINAPI d3d9_vertexbuffer_QueryInterface(IDirect3DVertexBuffer9 *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_IDirect3DVertexBuffer9)
31             || IsEqualGUID(riid, &IID_IDirect3DResource9)
32             || IsEqualGUID(riid, &IID_IUnknown))
33     {
34         IDirect3DVertexBuffer9_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 d3d9_vertexbuffer_AddRef(IDirect3DVertexBuffer9 *iface)
46 {
47     IDirect3DVertexBuffer9Impl *buffer = (IDirect3DVertexBuffer9Impl *)iface;
48     ULONG refcount = InterlockedIncrement(&buffer->ref);
49
50     TRACE("%p increasing refcount to %u.\n", iface, refcount);
51
52     if (refcount == 1)
53     {
54         IDirect3DDevice9Ex_AddRef(buffer->parentDevice);
55         wined3d_mutex_lock();
56         IWineD3DBuffer_AddRef(buffer->wineD3DVertexBuffer);
57         wined3d_mutex_unlock();
58     }
59
60     return refcount;
61 }
62
63 static ULONG WINAPI d3d9_vertexbuffer_Release(IDirect3DVertexBuffer9 *iface)
64 {
65     IDirect3DVertexBuffer9Impl *buffer = (IDirect3DVertexBuffer9Impl *)iface;
66     ULONG refcount = InterlockedDecrement(&buffer->ref);
67
68     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
69
70     if (!refcount)
71     {
72         IDirect3DDevice9Ex *device = buffer->parentDevice;
73
74         wined3d_mutex_lock();
75         IWineD3DBuffer_Release(buffer->wineD3DVertexBuffer);
76         wined3d_mutex_unlock();
77
78         /* Release the device last, as it may cause the device to be destroyed. */
79         IDirect3DDevice9Ex_Release(device);
80     }
81
82     return refcount;
83 }
84
85 static HRESULT WINAPI d3d9_vertexbuffer_GetDevice(IDirect3DVertexBuffer9 *iface, IDirect3DDevice9 **device)
86 {
87     TRACE("iface %p, device %p.\n", iface, device);
88
89     *device = (IDirect3DDevice9 *)((IDirect3DVertexBuffer9Impl *)iface)->parentDevice;
90     IDirect3DDevice9_AddRef(*device);
91
92     TRACE("Returning device %p.\n", *device);
93
94     return D3D_OK;
95 }
96
97 static HRESULT WINAPI d3d9_vertexbuffer_SetPrivateData(IDirect3DVertexBuffer9 *iface,
98         REFGUID guid, const void *data, DWORD data_size, DWORD flags)
99 {
100     HRESULT hr;
101
102     TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
103             iface, debugstr_guid(guid), data, data_size, flags);
104
105     wined3d_mutex_lock();
106     hr = IWineD3DBuffer_SetPrivateData(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer,
107             guid, data, data_size, flags);
108     wined3d_mutex_unlock();
109
110     return hr;
111 }
112
113 static HRESULT WINAPI d3d9_vertexbuffer_GetPrivateData(IDirect3DVertexBuffer9 *iface,
114         REFGUID guid, void *data, DWORD *data_size)
115 {
116     HRESULT hr;
117
118     TRACE("iface %p, guid %s, data %p, data_size %p.\n",
119             iface, debugstr_guid(guid), data, data_size);
120
121     wined3d_mutex_lock();
122     hr = IWineD3DBuffer_GetPrivateData(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer,
123             guid, data, data_size);
124     wined3d_mutex_unlock();
125
126     return hr;
127 }
128
129 static HRESULT WINAPI d3d9_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer9 *iface, REFGUID guid)
130 {
131     HRESULT hr;
132
133     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
134
135     wined3d_mutex_lock();
136     hr = IWineD3DBuffer_FreePrivateData(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer, guid);
137     wined3d_mutex_unlock();
138
139     return hr;
140 }
141
142 static DWORD WINAPI d3d9_vertexbuffer_SetPriority(IDirect3DVertexBuffer9 *iface, DWORD priority)
143 {
144     DWORD previous;
145
146     TRACE("iface %p, priority %u.\n", iface, priority);
147
148     wined3d_mutex_lock();
149     previous = IWineD3DBuffer_SetPriority(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer, priority);
150     wined3d_mutex_unlock();
151
152     return previous;
153 }
154
155 static DWORD WINAPI d3d9_vertexbuffer_GetPriority(IDirect3DVertexBuffer9 *iface)
156 {
157     DWORD priority;
158
159     TRACE("iface %p.\n", iface);
160
161     wined3d_mutex_lock();
162     priority = IWineD3DBuffer_GetPriority(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer);
163     wined3d_mutex_unlock();
164
165     return priority;
166 }
167
168 static void WINAPI d3d9_vertexbuffer_PreLoad(IDirect3DVertexBuffer9 *iface)
169 {
170     TRACE("iface %p.\n", iface);
171
172     wined3d_mutex_lock();
173     IWineD3DBuffer_PreLoad(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer);
174     wined3d_mutex_unlock();
175 }
176
177 static D3DRESOURCETYPE WINAPI d3d9_vertexbuffer_GetType(IDirect3DVertexBuffer9 *iface)
178 {
179     TRACE("iface %p.\n", iface);
180
181     return D3DRTYPE_VERTEXBUFFER;
182 }
183
184 static HRESULT WINAPI d3d9_vertexbuffer_Lock(IDirect3DVertexBuffer9 *iface,
185         UINT offset, UINT size, void **data, DWORD flags)
186 {
187     HRESULT hr;
188
189     TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n",
190             iface, offset, size, data, flags);
191
192     wined3d_mutex_lock();
193     hr = IWineD3DBuffer_Map(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer,
194             offset, size, (BYTE **)data, flags);
195     wined3d_mutex_unlock();
196
197     return hr;
198 }
199
200 static HRESULT WINAPI d3d9_vertexbuffer_Unlock(IDirect3DVertexBuffer9 *iface)
201 {
202     TRACE("iface %p.\n", iface);
203
204     wined3d_mutex_lock();
205     IWineD3DBuffer_Unmap(((IDirect3DVertexBuffer9Impl *)iface)->wineD3DVertexBuffer);
206     wined3d_mutex_unlock();
207
208     return D3D_OK;
209 }
210
211 static HRESULT WINAPI d3d9_vertexbuffer_GetDesc(IDirect3DVertexBuffer9 *iface, D3DVERTEXBUFFER_DESC *desc)
212 {
213     IDirect3DVertexBuffer9Impl *buffer = (IDirect3DVertexBuffer9Impl *)iface;
214     WINED3DBUFFER_DESC wined3d_desc;
215
216     TRACE("iface %p, desc %p.\n", iface, desc);
217
218     wined3d_mutex_lock();
219     IWineD3DBuffer_GetDesc(buffer->wineD3DVertexBuffer, &wined3d_desc);
220     wined3d_mutex_unlock();
221
222     desc->Format = D3DFMT_VERTEXDATA;
223     desc->Usage = wined3d_desc.Usage;
224     desc->Pool = wined3d_desc.Pool;
225     desc->Size = wined3d_desc.Size;
226     desc->Type = D3DRTYPE_VERTEXBUFFER;
227     desc->FVF = buffer->fvf;
228
229     return D3D_OK;
230 }
231
232 static const IDirect3DVertexBuffer9Vtbl d3d9_vertexbuffer_vtbl =
233 {
234     /* IUnknown */
235     d3d9_vertexbuffer_QueryInterface,
236     d3d9_vertexbuffer_AddRef,
237     d3d9_vertexbuffer_Release,
238     /* IDirect3DResource9 */
239     d3d9_vertexbuffer_GetDevice,
240     d3d9_vertexbuffer_SetPrivateData,
241     d3d9_vertexbuffer_GetPrivateData,
242     d3d9_vertexbuffer_FreePrivateData,
243     d3d9_vertexbuffer_SetPriority,
244     d3d9_vertexbuffer_GetPriority,
245     d3d9_vertexbuffer_PreLoad,
246     d3d9_vertexbuffer_GetType,
247     /* IDirect3DVertexBuffer9 */
248     d3d9_vertexbuffer_Lock,
249     d3d9_vertexbuffer_Unlock,
250     d3d9_vertexbuffer_GetDesc,
251 };
252
253 static void STDMETHODCALLTYPE d3d9_vertexbuffer_wined3d_object_destroyed(void *parent)
254 {
255     HeapFree(GetProcessHeap(), 0, parent);
256 }
257
258 static const struct wined3d_parent_ops d3d9_vertexbuffer_wined3d_parent_ops =
259 {
260     d3d9_vertexbuffer_wined3d_object_destroyed,
261 };
262
263 HRESULT vertexbuffer_init(IDirect3DVertexBuffer9Impl *buffer, IDirect3DDevice9Impl *device,
264         UINT size, UINT usage, DWORD fvf, D3DPOOL pool)
265 {
266     HRESULT hr;
267
268     buffer->lpVtbl = &d3d9_vertexbuffer_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, &d3d9_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 = (IDirect3DDevice9Ex *)device;
283     IDirect3DDevice9Ex_AddRef(buffer->parentDevice);
284
285     return D3D_OK;
286 }
287
288 static HRESULT WINAPI d3d9_indexbuffer_QueryInterface(IDirect3DIndexBuffer9 *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_IDirect3DIndexBuffer9)
293             || IsEqualGUID(riid, &IID_IDirect3DResource9)
294             || IsEqualGUID(riid, &IID_IUnknown))
295     {
296         IDirect3DIndexBuffer9_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 d3d9_indexbuffer_AddRef(IDirect3DIndexBuffer9 *iface)
308 {
309     IDirect3DIndexBuffer9Impl *buffer = (IDirect3DIndexBuffer9Impl *)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         IDirect3DDevice9Ex_AddRef(buffer->parentDevice);
317         wined3d_mutex_lock();
318         IWineD3DBuffer_AddRef(buffer->wineD3DIndexBuffer);
319         wined3d_mutex_unlock();
320     }
321
322     return refcount;
323 }
324
325 static ULONG WINAPI d3d9_indexbuffer_Release(IDirect3DIndexBuffer9 *iface)
326 {
327     IDirect3DIndexBuffer9Impl *buffer = (IDirect3DIndexBuffer9Impl *)iface;
328     ULONG refcount = InterlockedDecrement(&buffer->ref);
329
330     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
331
332     if (!refcount)
333     {
334         IDirect3DDevice9Ex *device = buffer->parentDevice;
335
336         wined3d_mutex_lock();
337         IWineD3DBuffer_Release(buffer->wineD3DIndexBuffer);
338         wined3d_mutex_unlock();
339
340         /* Release the device last, as it may cause the device to be destroyed. */
341         IDirect3DDevice9Ex_Release(device);
342     }
343
344     return refcount;
345 }
346
347 static HRESULT WINAPI d3d9_indexbuffer_GetDevice(IDirect3DIndexBuffer9 *iface, IDirect3DDevice9 **device)
348 {
349     TRACE("iface %p, device %p.\n", iface, device);
350
351     *device = (IDirect3DDevice9 *)((IDirect3DIndexBuffer9Impl *)iface)->parentDevice;
352     IDirect3DDevice9_AddRef(*device);
353
354     TRACE("Returning device %p.\n", *device);
355
356     return D3D_OK;
357 }
358
359 static HRESULT WINAPI d3d9_indexbuffer_SetPrivateData(IDirect3DIndexBuffer9 *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 = IWineD3DBuffer_SetPrivateData(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer,
369             guid, data, data_size, flags);
370     wined3d_mutex_unlock();
371
372     return hr;
373 }
374
375 static HRESULT WINAPI d3d9_indexbuffer_GetPrivateData(IDirect3DIndexBuffer9 *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 = IWineD3DBuffer_GetPrivateData(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer,
385             guid, data, data_size);
386     wined3d_mutex_unlock();
387
388     return hr;
389 }
390
391 static HRESULT WINAPI d3d9_indexbuffer_FreePrivateData(IDirect3DIndexBuffer9 *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 = IWineD3DBuffer_FreePrivateData(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer, guid);
399     wined3d_mutex_unlock();
400
401     return hr;
402 }
403
404 static DWORD WINAPI d3d9_indexbuffer_SetPriority(IDirect3DIndexBuffer9 *iface, DWORD priority)
405 {
406     DWORD previous;
407
408     TRACE("iface %p, priority %u.\n", iface, priority);
409
410     wined3d_mutex_lock();
411     previous = IWineD3DBuffer_SetPriority(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer, priority);
412     wined3d_mutex_unlock();
413
414     return previous;
415 }
416
417 static DWORD WINAPI d3d9_indexbuffer_GetPriority(IDirect3DIndexBuffer9 *iface)
418 {
419     DWORD priority;
420
421     TRACE("iface %p.\n", iface);
422
423     wined3d_mutex_lock();
424     priority = IWineD3DBuffer_GetPriority(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer);
425     wined3d_mutex_unlock();
426
427     return priority;
428 }
429
430 static void WINAPI d3d9_indexbuffer_PreLoad(IDirect3DIndexBuffer9 *iface)
431 {
432     TRACE("iface %p.\n", iface);
433
434     wined3d_mutex_lock();
435     IWineD3DBuffer_PreLoad(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer);
436     wined3d_mutex_unlock();
437 }
438
439 static D3DRESOURCETYPE WINAPI d3d9_indexbuffer_GetType(IDirect3DIndexBuffer9 *iface)
440 {
441     TRACE("iface %p.\n", iface);
442
443     return D3DRTYPE_INDEXBUFFER;
444 }
445
446 static HRESULT WINAPI d3d9_indexbuffer_Lock(IDirect3DIndexBuffer9 *iface,
447         UINT offset, UINT size, void **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 = IWineD3DBuffer_Map(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer,
456             offset, size, (BYTE **)data, flags);
457     wined3d_mutex_unlock();
458
459     return hr;
460 }
461
462 static HRESULT WINAPI d3d9_indexbuffer_Unlock(IDirect3DIndexBuffer9 *iface)
463 {
464     TRACE("iface %p.\n", iface);
465
466     wined3d_mutex_lock();
467     IWineD3DBuffer_Unmap(((IDirect3DIndexBuffer9Impl *)iface)->wineD3DIndexBuffer);
468     wined3d_mutex_unlock();
469
470     return D3D_OK;
471 }
472
473 static HRESULT WINAPI d3d9_indexbuffer_GetDesc(IDirect3DIndexBuffer9 *iface, D3DINDEXBUFFER_DESC *desc)
474 {
475     IDirect3DIndexBuffer9Impl *buffer = (IDirect3DIndexBuffer9Impl *)iface;
476     WINED3DBUFFER_DESC wined3d_desc;
477
478     TRACE("iface %p, desc %p.\n", iface, desc);
479
480     wined3d_mutex_lock();
481     IWineD3DBuffer_GetDesc(buffer->wineD3DIndexBuffer, &wined3d_desc);
482     wined3d_mutex_unlock();
483
484     desc->Format = d3dformat_from_wined3dformat(buffer->format);
485     desc->Usage = wined3d_desc.Usage;
486     desc->Pool = wined3d_desc.Pool;
487     desc->Size = wined3d_desc.Size;
488     desc->Type = D3DRTYPE_INDEXBUFFER;
489
490     return D3D_OK;
491 }
492
493 static const IDirect3DIndexBuffer9Vtbl d3d9_indexbuffer_vtbl =
494 {
495     /* IUnknown */
496     d3d9_indexbuffer_QueryInterface,
497     d3d9_indexbuffer_AddRef,
498     d3d9_indexbuffer_Release,
499     /* IDirect3DResource9 */
500     d3d9_indexbuffer_GetDevice,
501     d3d9_indexbuffer_SetPrivateData,
502     d3d9_indexbuffer_GetPrivateData,
503     d3d9_indexbuffer_FreePrivateData,
504     d3d9_indexbuffer_SetPriority,
505     d3d9_indexbuffer_GetPriority,
506     d3d9_indexbuffer_PreLoad,
507     d3d9_indexbuffer_GetType,
508     /* IDirect3DIndexBuffer9 */
509     d3d9_indexbuffer_Lock,
510     d3d9_indexbuffer_Unlock,
511     d3d9_indexbuffer_GetDesc,
512 };
513
514 static void STDMETHODCALLTYPE d3d9_indexbuffer_wined3d_object_destroyed(void *parent)
515 {
516     HeapFree(GetProcessHeap(), 0, parent);
517 }
518
519 static const struct wined3d_parent_ops d3d9_indexbuffer_wined3d_parent_ops =
520 {
521     d3d9_indexbuffer_wined3d_object_destroyed,
522 };
523
524 HRESULT indexbuffer_init(IDirect3DIndexBuffer9Impl *buffer, IDirect3DDevice9Impl *device,
525         UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool)
526 {
527     HRESULT hr;
528
529     buffer->lpVtbl = &d3d9_indexbuffer_vtbl;
530     buffer->ref = 1;
531     buffer->format = wined3dformat_from_d3dformat(format);
532
533     wined3d_mutex_lock();
534     hr = IWineD3DDevice_CreateIndexBuffer(device->WineD3DDevice, size, usage & WINED3DUSAGE_MASK,
535             (WINED3DPOOL)pool, buffer, &d3d9_indexbuffer_wined3d_parent_ops, &buffer->wineD3DIndexBuffer);
536     wined3d_mutex_unlock();
537     if (FAILED(hr))
538     {
539         WARN("Failed to create wined3d buffer, hr %#x.\n", hr);
540         return hr;
541     }
542
543     buffer->parentDevice = (IDirect3DDevice9Ex *)device;
544     IDirect3DDevice9Ex_AddRef(buffer->parentDevice);
545
546     return D3D_OK;
547 }