Check to see if the vertex declaration is null before trying to
[wine] / dlls / wined3d / volume.c
1 /*
2  * IWineD3DVolume implementation
3  *
4  * Copyright 2002-2005 Jason Edmeades
5  * Copyright 2002-2005 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wined3d_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
27 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
28
29 /* *******************************************
30    IWineD3DVolume IUnknown parts follow
31    ******************************************* */
32 HRESULT WINAPI IWineD3DVolumeImpl_QueryInterface(IWineD3DVolume *iface, REFIID riid, LPVOID *ppobj)
33 {
34     IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
35     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
36     if (IsEqualGUID(riid, &IID_IUnknown)
37         || IsEqualGUID(riid, &IID_IWineD3DVolume)){
38         IUnknown_AddRef(iface);
39         *ppobj = This;
40         return D3D_OK;
41     }
42     return E_NOINTERFACE;
43 }
44
45 ULONG WINAPI IWineD3DVolumeImpl_AddRef(IWineD3DVolume *iface) {
46     IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
47     TRACE("(%p) : AddRef increasing from %ld\n", This, This->resource.ref);
48     return InterlockedIncrement(&This->resource.ref);
49 }
50
51 ULONG WINAPI IWineD3DVolumeImpl_Release(IWineD3DVolume *iface) {
52     IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
53     ULONG ref;
54     TRACE("(%p) : Releasing from %ld\n", This, This->resource.ref);
55     ref = InterlockedDecrement(&This->resource.ref);
56     if (ref == 0) {
57         IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
58         HeapFree(GetProcessHeap(), 0, This);
59     }
60     return ref;
61 }
62
63 /* ****************************************************
64    IWineD3DSurface IWineD3DResource parts follow
65    **************************************************** */
66 HRESULT WINAPI IWineD3DVolumeImpl_GetParent(IWineD3DVolume *iface, IUnknown **pParent) {
67     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
68 }
69
70 HRESULT WINAPI IWineD3DVolumeImpl_GetDevice(IWineD3DVolume *iface, IWineD3DDevice** ppDevice) {
71     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
72 }
73
74 HRESULT WINAPI IWineD3DVolumeImpl_SetPrivateData(IWineD3DVolume *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
75     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
76 }
77
78 HRESULT WINAPI IWineD3DVolumeImpl_GetPrivateData(IWineD3DVolume *iface, REFGUID  refguid, void* pData, DWORD* pSizeOfData) {
79     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
80 }
81
82 HRESULT WINAPI IWineD3DVolumeImpl_FreePrivateData(IWineD3DVolume *iface, REFGUID refguid) {
83     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
84 }
85
86 DWORD WINAPI IWineD3DVolumeImpl_SetPriority(IWineD3DVolume *iface, DWORD PriorityNew) {
87     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
88 }
89
90 DWORD WINAPI IWineD3DVolumeImpl_GetPriority(IWineD3DVolume *iface) {
91     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
92 }
93
94 void WINAPI IWineD3DVolumeImpl_PreLoad(IWineD3DVolume *iface) {
95     return IWineD3DResourceImpl_PreLoad((IWineD3DResource *)iface);
96 }
97
98 D3DRESOURCETYPE WINAPI IWineD3DVolumeImpl_GetType(IWineD3DVolume *iface) {
99     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
100 }
101
102 /* *******************************************
103    IWineD3DVolume parts follow
104    ******************************************* */
105 HRESULT WINAPI IWineD3DVolumeImpl_GetContainer(IWineD3DVolume *iface, REFIID riid, void** ppContainer) {
106     IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
107     TRACE("(%p) : returning %p\n", This, This->container);
108     *ppContainer = This->container;
109     IUnknown_AddRef(This->container);
110     return D3D_OK;
111 }
112
113 HRESULT WINAPI IWineD3DVolumeImpl_GetDesc(IWineD3DVolume *iface, WINED3DVOLUME_DESC* pDesc) {
114     IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
115     TRACE("(%p) : copying into %p\n", This, pDesc);
116     
117     *(pDesc->Format)  = This->resource.format;
118     *(pDesc->Type)    = This->resource.resourceType;
119     *(pDesc->Usage)   = This->resource.usage;
120     *(pDesc->Pool)    = This->resource.pool;
121     *(pDesc->Size)    = This->resource.size; /* dx8 only */
122     *(pDesc->Width)   = This->currentDesc.Width;
123     *(pDesc->Height)  = This->currentDesc.Height;
124     *(pDesc->Depth)   = This->currentDesc.Depth;
125     return D3D_OK;
126 }
127
128 HRESULT WINAPI IWineD3DVolumeImpl_LockBox(IWineD3DVolume *iface, D3DLOCKED_BOX* pLockedVolume, CONST D3DBOX* pBox, DWORD Flags) {
129     IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
130     FIXME("(%p) : pBox=%p stub\n", This, pBox);    
131
132     /* fixme: should we really lock as such? */
133     TRACE("(%p) : box=%p, output pbox=%p, allMem=%p\n", This, pBox, pLockedVolume, This->resource.allocatedMemory);
134
135     pLockedVolume->RowPitch   = This->bytesPerPixel * This->currentDesc.Width;                        /* Bytes / row   */
136     pLockedVolume->SlicePitch = This->bytesPerPixel * This->currentDesc.Width * This->currentDesc.Height;  /* Bytes / slice */
137     if (!pBox) {
138         TRACE("No box supplied - all is ok\n");
139         pLockedVolume->pBits = This->resource.allocatedMemory;
140         This->lockedBox.Left   = 0;
141         This->lockedBox.Top    = 0;
142         This->lockedBox.Front  = 0;
143         This->lockedBox.Right  = This->currentDesc.Width;
144         This->lockedBox.Bottom = This->currentDesc.Height;
145         This->lockedBox.Back   = This->currentDesc.Depth;
146     } else {
147         TRACE("Lock Box (%p) = l %d, t %d, r %d, b %d, fr %d, ba %d\n", pBox, pBox->Left, pBox->Top, pBox->Right, pBox->Bottom, pBox->Front, pBox->Back);
148         pLockedVolume->pBits = This->resource.allocatedMemory + 
149           (pLockedVolume->SlicePitch * pBox->Front) + /* FIXME: is front < back or vica versa? */
150           (pLockedVolume->RowPitch * pBox->Top) + 
151           (pBox->Left * This->bytesPerPixel);
152         This->lockedBox.Left   = pBox->Left;
153         This->lockedBox.Top    = pBox->Top;
154         This->lockedBox.Front  = pBox->Front;
155         This->lockedBox.Right  = pBox->Right;
156         This->lockedBox.Bottom = pBox->Bottom;
157         This->lockedBox.Back   = pBox->Back;
158     }
159     
160     if (Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY)) {
161       /* Don't dirtify */
162     } else {
163       /**
164        * Dirtify on lock
165        * as seen in msdn docs
166        */
167       IWineD3DVolume_AddDirtyBox(iface, &This->lockedBox);
168
169       /**  Dirtify Container if needed */
170       if (NULL != This->container) {
171
172         IWineD3DVolumeTexture *cont = (IWineD3DVolumeTexture*) This->container;        
173         D3DRESOURCETYPE containerType = IWineD3DBaseTexture_GetType((IWineD3DBaseTexture *) cont);
174
175         if (containerType == D3DRTYPE_VOLUMETEXTURE) {
176           IWineD3DBaseTextureImpl* pTexture = (IWineD3DBaseTextureImpl*) cont;
177           pTexture->baseTexture.dirty = TRUE;
178         } else {
179           FIXME("Set dirty on container type %d\n", containerType);
180         }
181       }
182     }
183
184     This->locked = TRUE;
185     TRACE("returning memory@%p rpitch(%d) spitch(%d)\n", pLockedVolume->pBits, pLockedVolume->RowPitch, pLockedVolume->SlicePitch);
186     return D3D_OK;
187 }
188
189 HRESULT WINAPI IWineD3DVolumeImpl_UnlockBox(IWineD3DVolume *iface) {
190     IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
191     if (FALSE == This->locked) {
192       ERR("trying to lock unlocked volume@%p\n", This);  
193       return D3DERR_INVALIDCALL;
194     }
195     TRACE("(%p) : unlocking volume\n", This);
196     This->locked = FALSE;
197     memset(&This->lockedBox, 0, sizeof(RECT));
198     return D3D_OK;
199 }
200
201 /* Internal use functions follow : */
202
203 HRESULT WINAPI IWineD3DVolumeImpl_CleanDirtyBox(IWineD3DVolume *iface) {
204   IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
205   This->dirty = FALSE;
206   This->lockedBox.Left   = This->currentDesc.Width;
207   This->lockedBox.Top    = This->currentDesc.Height;
208   This->lockedBox.Front  = This->currentDesc.Depth;  
209   This->lockedBox.Right  = 0;
210   This->lockedBox.Bottom = 0;
211   This->lockedBox.Back   = 0;
212   return D3D_OK;
213 }
214
215 HRESULT WINAPI IWineD3DVolumeImpl_AddDirtyBox(IWineD3DVolume *iface, CONST D3DBOX* pDirtyBox) {
216   IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
217   This->dirty = TRUE;
218    if (NULL != pDirtyBox) {
219     This->lockedBox.Left   = min(This->lockedBox.Left,   pDirtyBox->Left);
220     This->lockedBox.Top    = min(This->lockedBox.Top,    pDirtyBox->Top);
221     This->lockedBox.Front  = min(This->lockedBox.Front,  pDirtyBox->Front);
222     This->lockedBox.Right  = max(This->lockedBox.Right,  pDirtyBox->Right);
223     This->lockedBox.Bottom = max(This->lockedBox.Bottom, pDirtyBox->Bottom);
224     This->lockedBox.Back   = max(This->lockedBox.Back,   pDirtyBox->Back);
225   } else {
226     This->lockedBox.Left   = 0;
227     This->lockedBox.Top    = 0;
228     This->lockedBox.Front  = 0;
229     This->lockedBox.Right  = This->currentDesc.Width;
230     This->lockedBox.Bottom = This->currentDesc.Height;
231     This->lockedBox.Back   = This->currentDesc.Depth;
232   }
233   return D3D_OK;
234 }
235
236 HRESULT WINAPI IWineD3DVolumeImpl_SetContainer(IWineD3DVolume *iface, IUnknown* container){
237   IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
238   
239   This->container = container;
240   return D3D_OK;
241 }
242
243 HRESULT WINAPI IWineD3DVolumeImpl_LoadTexture(IWineD3DVolume *iface, GLenum gl_level) {
244     IWineD3DVolumeImpl *This     = (IWineD3DVolumeImpl *)iface;
245     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
246
247     TRACE("Calling glTexImage3D %x level=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%x, Mem=%p\n",
248             GL_TEXTURE_3D,
249             gl_level,
250             D3DFmt2GLIntFmt(myDevice, This->currentDesc.Format),
251             This->currentDesc.Width,
252             This->currentDesc.Height,
253             This->currentDesc.Depth,
254             0,
255             D3DFmt2GLFmt(myDevice, This->currentDesc.Format),
256             D3DFmt2GLType(myDevice, This->currentDesc.Format),
257             This->resource.allocatedMemory);
258     glTexImage3D(GL_TEXTURE_3D,
259                     gl_level,
260                     D3DFmt2GLIntFmt(myDevice, This->currentDesc.Format),
261                     This->currentDesc.Width,
262                     This->currentDesc.Height,
263                     This->currentDesc.Depth,
264                     0,
265                     D3DFmt2GLFmt(myDevice, This->currentDesc.Format),
266                     D3DFmt2GLType(myDevice, This->currentDesc.Format),
267                     This->resource.allocatedMemory);
268     checkGLcall("glTexImage3D");
269     return D3D_OK;
270     
271 }
272
273 const IWineD3DVolumeVtbl IWineD3DVolume_Vtbl =
274 {
275     /* IUnknown */
276     IWineD3DVolumeImpl_QueryInterface,
277     IWineD3DVolumeImpl_AddRef,
278     IWineD3DVolumeImpl_Release,
279     /* IWineD3DResource */
280     IWineD3DVolumeImpl_GetParent,
281     IWineD3DVolumeImpl_GetDevice,
282     IWineD3DVolumeImpl_SetPrivateData,
283     IWineD3DVolumeImpl_GetPrivateData,
284     IWineD3DVolumeImpl_FreePrivateData,
285     IWineD3DVolumeImpl_SetPriority,
286     IWineD3DVolumeImpl_GetPriority,
287     IWineD3DVolumeImpl_PreLoad,
288     IWineD3DVolumeImpl_GetType,
289     /* IWineD3DVolume */
290     IWineD3DVolumeImpl_GetContainer,
291     IWineD3DVolumeImpl_GetDesc,
292     IWineD3DVolumeImpl_LockBox,
293     IWineD3DVolumeImpl_UnlockBox,
294     /* Internal interface */    
295     IWineD3DVolumeImpl_AddDirtyBox,
296     IWineD3DVolumeImpl_CleanDirtyBox,
297     IWineD3DVolumeImpl_LoadTexture,
298     IWineD3DVolumeImpl_SetContainer
299 };