wined3d: Don't free D3D surfaces until the wined3d surface is destroyed.
[wine] / dlls / d3d9 / vertexbuffer.c
1 /*
2  * IDirect3DVertexBuffer9 implementation
3  *
4  * Copyright 2002-2004 Jason Edmeades
5  * Copyright 2002-2004 Raphael Junqueira
6  * Copyright 2005 Oliver Stieber
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "d3d9_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
27
28 /* IDirect3DVertexBuffer9 IUnknown parts follow: */
29 static HRESULT WINAPI IDirect3DVertexBuffer9Impl_QueryInterface(LPDIRECT3DVERTEXBUFFER9 iface, REFIID riid, LPVOID* ppobj) {
30     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
31
32     if (IsEqualGUID(riid, &IID_IUnknown)
33         || IsEqualGUID(riid, &IID_IDirect3DResource9)
34         || IsEqualGUID(riid, &IID_IDirect3DVertexBuffer9)) {
35         IDirect3DVertexBuffer9_AddRef(iface);
36         *ppobj = This;
37         return S_OK;
38     }
39
40     WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
41     *ppobj = NULL;
42     return E_NOINTERFACE;
43 }
44
45 static ULONG WINAPI IDirect3DVertexBuffer9Impl_AddRef(LPDIRECT3DVERTEXBUFFER9 iface) {
46     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
47     ULONG ref = InterlockedIncrement(&This->ref);
48
49     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
50
51     return ref;
52 }
53
54 static ULONG WINAPI IDirect3DVertexBuffer9Impl_Release(LPDIRECT3DVERTEXBUFFER9 iface) {
55     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
56     ULONG ref = InterlockedDecrement(&This->ref);
57
58     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
59
60     if (ref == 0) {
61         wined3d_mutex_lock();
62         IWineD3DBuffer_Release(This->wineD3DVertexBuffer);
63         wined3d_mutex_unlock();
64
65         IDirect3DDevice9Ex_Release(This->parentDevice);
66         HeapFree(GetProcessHeap(), 0, This);
67     }
68     return ref;
69 }
70
71 /* IDirect3DVertexBuffer9 IDirect3DResource9 Interface follow: */
72 static HRESULT WINAPI IDirect3DVertexBuffer9Impl_GetDevice(LPDIRECT3DVERTEXBUFFER9 iface, IDirect3DDevice9** ppDevice) {
73     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
74     IWineD3DDevice *wined3d_device;
75     HRESULT hr;
76     TRACE("(%p) Relay\n", This);
77
78     wined3d_mutex_lock();
79     hr = IWineD3DBuffer_GetDevice(This->wineD3DVertexBuffer, &wined3d_device);
80     if (SUCCEEDED(hr))
81     {
82         IWineD3DDevice_GetParent(wined3d_device, (IUnknown **)ppDevice);
83         IWineD3DDevice_Release(wined3d_device);
84     }
85     wined3d_mutex_unlock();
86
87     return hr;
88 }
89
90 static HRESULT WINAPI IDirect3DVertexBuffer9Impl_SetPrivateData(LPDIRECT3DVERTEXBUFFER9 iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
91     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
92     HRESULT hr;
93
94     TRACE("(%p) Relay\n", This);
95
96     wined3d_mutex_lock();
97     hr = IWineD3DBuffer_SetPrivateData(This->wineD3DVertexBuffer, refguid, pData, SizeOfData, Flags);
98     wined3d_mutex_unlock();
99
100     return hr;
101 }
102
103 static HRESULT WINAPI IDirect3DVertexBuffer9Impl_GetPrivateData(LPDIRECT3DVERTEXBUFFER9 iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
104     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
105     HRESULT hr;
106     TRACE("(%p) Relay\n", This);
107
108     wined3d_mutex_lock();
109     hr = IWineD3DBuffer_GetPrivateData(This->wineD3DVertexBuffer, refguid, pData, pSizeOfData);
110     wined3d_mutex_unlock();
111
112     return hr;
113 }
114
115 static HRESULT WINAPI IDirect3DVertexBuffer9Impl_FreePrivateData(LPDIRECT3DVERTEXBUFFER9 iface, REFGUID refguid) {
116     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
117     HRESULT hr;
118     TRACE("(%p) Relay\n", This);
119
120     wined3d_mutex_lock();
121     hr = IWineD3DBuffer_FreePrivateData(This->wineD3DVertexBuffer, refguid);
122     wined3d_mutex_unlock();
123
124     return hr;
125 }
126
127 static DWORD WINAPI IDirect3DVertexBuffer9Impl_SetPriority(LPDIRECT3DVERTEXBUFFER9 iface, DWORD PriorityNew) {
128     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
129     HRESULT hr;
130     TRACE("(%p) Relay\n", This);
131
132     wined3d_mutex_lock();
133     hr = IWineD3DBuffer_SetPriority(This->wineD3DVertexBuffer, PriorityNew);
134     wined3d_mutex_unlock();
135
136     return hr;
137 }
138
139 static DWORD WINAPI IDirect3DVertexBuffer9Impl_GetPriority(LPDIRECT3DVERTEXBUFFER9 iface) {
140     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
141     HRESULT hr;
142     TRACE("(%p) Relay\n", This);
143
144     wined3d_mutex_lock();
145     hr = IWineD3DBuffer_GetPriority(This->wineD3DVertexBuffer);
146     wined3d_mutex_unlock();
147
148     return hr;
149 }
150
151 static void WINAPI IDirect3DVertexBuffer9Impl_PreLoad(LPDIRECT3DVERTEXBUFFER9 iface) {
152     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
153     TRACE("(%p) Relay\n", This);
154
155     wined3d_mutex_lock();
156     IWineD3DBuffer_PreLoad(This->wineD3DVertexBuffer);
157     wined3d_mutex_unlock();
158 }
159
160 static D3DRESOURCETYPE WINAPI IDirect3DVertexBuffer9Impl_GetType(LPDIRECT3DVERTEXBUFFER9 iface) {
161     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
162     TRACE("(%p)\n", This);
163
164     return D3DRTYPE_VERTEXBUFFER;
165 }
166
167 /* IDirect3DVertexBuffer9 Interface follow: */
168 static HRESULT WINAPI IDirect3DVertexBuffer9Impl_Lock(LPDIRECT3DVERTEXBUFFER9 iface, UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags) {
169     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
170     HRESULT hr;
171     TRACE("(%p) Relay\n", This);
172
173     wined3d_mutex_lock();
174     hr = IWineD3DBuffer_Map(This->wineD3DVertexBuffer, OffsetToLock, SizeToLock, (BYTE **)ppbData, Flags);
175     wined3d_mutex_unlock();
176
177     return hr;
178 }
179
180 static HRESULT WINAPI IDirect3DVertexBuffer9Impl_Unlock(LPDIRECT3DVERTEXBUFFER9 iface) {
181     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
182     HRESULT hr;
183     TRACE("(%p) Relay\n", This);
184
185     wined3d_mutex_lock();
186     hr = IWineD3DBuffer_Unmap(This->wineD3DVertexBuffer);
187     wined3d_mutex_unlock();
188
189     return hr;
190 }
191
192 static HRESULT WINAPI IDirect3DVertexBuffer9Impl_GetDesc(LPDIRECT3DVERTEXBUFFER9 iface, D3DVERTEXBUFFER_DESC* pDesc) {
193     IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface;
194     HRESULT hr;
195     WINED3DBUFFER_DESC desc;
196     TRACE("(%p) Relay\n", This);
197
198     wined3d_mutex_lock();
199     hr = IWineD3DBuffer_GetDesc(This->wineD3DVertexBuffer, &desc);
200     wined3d_mutex_unlock();
201
202     if (SUCCEEDED(hr)) {
203         pDesc->Format = D3DFMT_VERTEXDATA;
204         pDesc->Usage = desc.Usage;
205         pDesc->Pool = desc.Pool;
206         pDesc->Size = desc.Size;
207         pDesc->Type = D3DRTYPE_VERTEXBUFFER;
208         pDesc->FVF = This->fvf;
209     }
210
211
212     return hr;
213 }
214
215 static const IDirect3DVertexBuffer9Vtbl Direct3DVertexBuffer9_Vtbl =
216 {
217     /* IUnknown */
218     IDirect3DVertexBuffer9Impl_QueryInterface,
219     IDirect3DVertexBuffer9Impl_AddRef,
220     IDirect3DVertexBuffer9Impl_Release,
221     /* IDirect3DResource9 */
222     IDirect3DVertexBuffer9Impl_GetDevice,
223     IDirect3DVertexBuffer9Impl_SetPrivateData,
224     IDirect3DVertexBuffer9Impl_GetPrivateData,
225     IDirect3DVertexBuffer9Impl_FreePrivateData,
226     IDirect3DVertexBuffer9Impl_SetPriority,
227     IDirect3DVertexBuffer9Impl_GetPriority,
228     IDirect3DVertexBuffer9Impl_PreLoad,
229     IDirect3DVertexBuffer9Impl_GetType,
230     /* IDirect3DVertexBuffer9 */
231     IDirect3DVertexBuffer9Impl_Lock,
232     IDirect3DVertexBuffer9Impl_Unlock,
233     IDirect3DVertexBuffer9Impl_GetDesc
234 };
235
236
237 /* IDirect3DDevice9 IDirect3DVertexBuffer9 Methods follow: */
238 HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(IDirect3DDevice9Ex *iface, UINT Size, DWORD Usage,
239         DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle)
240 {
241     IDirect3DVertexBuffer9Impl *object;
242     IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
243     HRESULT hrc = D3D_OK;
244
245     /* Allocate the storage for the device */
246     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer9Impl));
247     if (NULL == object) {
248         FIXME("Allocation of memory failed, returning D3DERR_OUTOFVIDEOMEMORY\n");
249         return D3DERR_OUTOFVIDEOMEMORY;
250     }
251
252     object->lpVtbl = &Direct3DVertexBuffer9_Vtbl;
253     object->ref = 1;
254     object->fvf = FVF;
255
256     wined3d_mutex_lock();
257     hrc = IWineD3DDevice_CreateVertexBuffer(This->WineD3DDevice, Size, Usage & WINED3DUSAGE_MASK,
258             0 /* fvf for ddraw only */, (WINED3DPOOL) Pool, &(object->wineD3DVertexBuffer), (IUnknown *)object);
259     wined3d_mutex_unlock();
260
261     if (hrc != D3D_OK) {
262
263         /* free up object */
264         WARN("(%p) call to IWineD3DDevice_CreateVertexBuffer failed\n", This);
265         HeapFree(GetProcessHeap(), 0, object);
266     } else {
267         IDirect3DDevice9Ex_AddRef(iface);
268         object->parentDevice = iface;
269         TRACE("(%p) : Created vertex buffer %p\n", This, object);
270         *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER9) object;
271     }
272     return hrc;
273 }