- Volume now inherits Resource. This isn't the way Microsoft implements
[wine] / dlls / wined3d / basetexture.c
1 /*
2  * IWineD3DBaseTexture 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., 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->resource.wineD3DDevice)->wineD3D))->gl_info
28
29 /* *******************************************
30    IWineD3DBaseTexture IUnknown parts follow
31    ******************************************* */
32 HRESULT WINAPI IWineD3DBaseTextureImpl_QueryInterface(IWineD3DBaseTexture *iface, REFIID riid, LPVOID *ppobj)
33 {
34     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;   
35     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);        
36     /* FIXME: This needs to extend an IWineD3DBaseObject */        
37     if (IsEqualGUID(riid, &IID_IUnknown)     
38         || IsEqualGUID(riid, &IID_IWineD3DResource)   
39         || IsEqualGUID(riid, &IID_IWineD3DBaseTexture)) {
40         IUnknown_AddRef(iface);
41         *ppobj = This;
42         return D3D_OK;
43     }        
44     return E_NOINTERFACE;
45 }
46
47 ULONG WINAPI IWineD3DBaseTextureImpl_AddRef(IWineD3DBaseTexture *iface) {
48     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
49     ULONG ref = InterlockedIncrement(&This->resource.ref);
50     
51     TRACE("(%p) : AddRef increasing from %ld\n", This,ref - 1);
52     IUnknown_AddRef(This->resource.parent);
53     return ref;
54 }
55
56 ULONG WINAPI IWineD3DBaseTextureImpl_Release(IWineD3DBaseTexture *iface) {
57     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
58     ULONG ref = InterlockedDecrement(&This->resource.ref);
59     TRACE("(%p) : Releasing from %ld\n", This, ref + 1);
60     if (ref == 0) {
61         IWineD3DBaseTextureImpl_CleanUp(iface);
62         HeapFree(GetProcessHeap(), 0, This);
63     } else {
64         IUnknown_Release(This->resource.parent);  /* Released the reference to the d3dx object */
65     }
66     return ref;
67 }
68
69 /* class static */
70 void IWineD3DBaseTextureImpl_CleanUp(IWineD3DBaseTexture *iface){
71     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
72     TRACE("(%p) : ", This);
73     if (This->baseTexture.textureName != 0) {
74         ENTER_GL();
75         TRACE("Deleting texture %d\n", This->baseTexture.textureName);
76         glDeleteTextures(1, &This->baseTexture.textureName);
77         LEAVE_GL();
78     }
79     IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
80 }
81
82 /* ****************************************************
83    IWineD3DBaseTexture IWineD3DResource parts follow
84    **************************************************** */
85 HRESULT WINAPI IWineD3DBaseTextureImpl_GetDevice(IWineD3DBaseTexture *iface, IWineD3DDevice** ppDevice) {
86     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
87 }
88
89 HRESULT WINAPI IWineD3DBaseTextureImpl_SetPrivateData(IWineD3DBaseTexture *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
90     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
91 }
92
93 HRESULT WINAPI IWineD3DBaseTextureImpl_GetPrivateData(IWineD3DBaseTexture *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
94     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
95 }
96
97 HRESULT WINAPI IWineD3DBaseTextureImpl_FreePrivateData(IWineD3DBaseTexture *iface, REFGUID refguid) {
98     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
99 }
100
101 DWORD    WINAPI        IWineD3DBaseTextureImpl_SetPriority(IWineD3DBaseTexture *iface, DWORD PriorityNew) {
102     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
103 }
104
105 DWORD    WINAPI        IWineD3DBaseTextureImpl_GetPriority(IWineD3DBaseTexture *iface) {
106     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
107 }
108
109 void     WINAPI        IWineD3DBaseTextureImpl_PreLoad(IWineD3DBaseTexture *iface) {
110     return IWineD3DResourceImpl_PreLoad((IWineD3DResource *)iface);
111 }
112
113 D3DRESOURCETYPE WINAPI IWineD3DBaseTextureImpl_GetType(IWineD3DBaseTexture *iface) {
114     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
115 }
116
117 HRESULT WINAPI IWineD3DBaseTextureImpl_GetParent(IWineD3DBaseTexture *iface, IUnknown **pParent) {
118     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
119 }
120
121 /* ******************************************************
122    IWineD3DBaseTexture IWineD3DBaseTexture parts follow
123    ****************************************************** */
124
125 /* There is no OpenGL equivilent of setLOD, getLOD, all they do it priortise testure loading
126  * so just pretend that they work unless something really needs a failure. */
127 DWORD WINAPI IWineD3DBaseTextureImpl_SetLOD(IWineD3DBaseTexture *iface, DWORD LODNew) {
128     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
129     
130     if (This->resource.pool != D3DPOOL_MANAGED) {
131         return  D3DERR_INVALIDCALL;
132     }    
133     
134     if(LODNew >= This->baseTexture.levels)
135         LODNew = This->baseTexture.levels - 1;
136      This->baseTexture.LOD = LODNew;
137     
138     TRACE("(%p) : set bogus LOD to %d \n", This, This->baseTexture.LOD);
139     
140     return This->baseTexture.LOD;
141 }
142
143 DWORD WINAPI IWineD3DBaseTextureImpl_GetLOD(IWineD3DBaseTexture *iface) {
144     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
145     
146     if (This->resource.pool != D3DPOOL_MANAGED) {
147         return  D3DERR_INVALIDCALL;
148     }
149     
150     TRACE("(%p) : returning %d \n", This, This->baseTexture.LOD);
151     
152     return This->baseTexture.LOD;
153 }
154
155 DWORD WINAPI IWineD3DBaseTextureImpl_GetLevelCount(IWineD3DBaseTexture *iface) {
156     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
157     TRACE("(%p) : returning %d\n", This, This->baseTexture.levels);    
158     return This->baseTexture.levels;
159 }
160
161 HRESULT WINAPI IWineD3DBaseTextureImpl_SetAutoGenFilterType(IWineD3DBaseTexture *iface, D3DTEXTUREFILTERTYPE FilterType) {
162   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
163
164   if (!(This->baseTexture.usage & D3DUSAGE_AUTOGENMIPMAP)) {
165       TRACE("(%p) : returning invalid call\n", This);
166       return D3DERR_INVALIDCALL;
167   }
168   This->baseTexture.filterType = FilterType;
169   TRACE("(%p) : \n", This);
170   return D3D_OK;
171 }
172
173 D3DTEXTUREFILTERTYPE WINAPI IWineD3DBaseTextureImpl_GetAutoGenFilterType(IWineD3DBaseTexture *iface) {
174   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
175   FIXME("(%p) : stub\n", This);
176   if (!(This->baseTexture.usage & D3DUSAGE_AUTOGENMIPMAP)) {
177      return D3DTEXF_NONE;
178   }
179   return This->baseTexture.filterType;
180   return D3DTEXF_LINEAR; /* default */
181 }
182
183 void WINAPI IWineD3DBaseTextureImpl_GenerateMipSubLevels(IWineD3DBaseTexture *iface) {
184   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
185   /* TODO: implement filters using GL_SGI_generate_mipmaps http://oss.sgi.com/projects/ogl-sample/registry/SGIS/generate_mipmap.txt */  
186   FIXME("(%p) : stub\n", This);
187   return ;
188 }
189
190 /* Internal function, No d3d mapping */
191 BOOL WINAPI IWineD3DBaseTextureImpl_SetDirty(IWineD3DBaseTexture *iface, BOOL dirty) {
192     BOOL old;
193     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
194     old = This->baseTexture.dirty;
195     This->baseTexture.dirty = dirty;
196     return old;
197 }
198
199 BOOL WINAPI IWineD3DBaseTextureImpl_GetDirty(IWineD3DBaseTexture *iface) {
200     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
201     return This->baseTexture.dirty;
202 }
203
204 HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) {
205     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
206     UINT textureDimensions;
207
208     TRACE("(%p) : About to bind texture\n", This);
209
210     textureDimensions = IWineD3DCubeTexture_GetTextureDimensions(iface);
211     ENTER_GL();
212 #if 0 /* TODO: context manager support */
213      IWineD3DContextManager_PushState(This->contextManager, textureDimensions, ENABLED, NOW /* make sure the state is applied now */);
214 #else    
215     glEnable(textureDimensions);
216 #endif
217
218     /* Generate a texture name if we don't already have one */
219     if (This->baseTexture.textureName == 0) {
220         glGenTextures(1, &This->baseTexture.textureName);
221         checkGLcall("glGenTextures");
222         TRACE("Generated texture %d\n", This->baseTexture.textureName);
223          if (This->resource.pool == D3DPOOL_DEFAULT) {
224             /* Tell opengl to try and keep this texture in video ram (well mostly) */
225             GLclampf tmp;
226             tmp = 0.9f;
227             glPrioritizeTextures(1, &This->baseTexture.textureName, &tmp);
228          }        
229     }
230
231     /* Bind the texture */
232     if (This->baseTexture.textureName != 0) {
233         glBindTexture(textureDimensions, This->baseTexture.textureName);
234         checkGLcall("glBindTexture");
235     } else { /* this only happened if we've run out of openGL textures */
236         WARN("This texture doesn't have an openGL texture assigned to it\n");
237         return D3DERR_INVALIDCALL;
238     }
239
240     /* Always need to reset the number of mipmap levels when rebinding as it is
241        a property of the active texture unit, and another texture may have set it
242        to a different value                                                       */
243     TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", This->baseTexture.levels - 1);
244     glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels - 1);
245     checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels)");
246     
247     return D3D_OK;
248 }
249 HRESULT WINAPI IWineD3DBaseTextureImpl_UnBindTexture(IWineD3DBaseTexture *iface) {
250     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
251     UINT textureDimensions;
252
253     TRACE("(%p) : About to bind texture\n", This);
254     textureDimensions = IWineD3DCubeTexture_GetTextureDimensions(iface);
255
256     ENTER_GL();
257     
258     glBindTexture(textureDimensions, 0);
259 #if 0 /* TODO: context manager support */
260      IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_CUBE_MAP_ARB, ENABLED, NOW /* make sure the state is applied now */);
261 #else    
262     glDisable(textureDimensions);
263 #endif
264     
265     LEAVE_GL();
266     return D3D_OK;
267 }
268
269 UINT WINAPI IWineD3DBaseTextureImpl_GetTextureDimensions(IWineD3DBaseTexture *iface){
270     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
271     FIXME("(%p) : This shouldn't be called\n", This);
272     return D3D_OK;
273 }
274
275 IWineD3DBaseTextureVtbl IWineD3DBaseTexture_Vtbl =
276 {
277     IWineD3DBaseTextureImpl_QueryInterface,
278     IWineD3DBaseTextureImpl_AddRef,
279     IWineD3DBaseTextureImpl_Release,
280     /* IWineD3DResource */
281     IWineD3DBaseTextureImpl_GetParent,
282     IWineD3DBaseTextureImpl_GetDevice,
283     IWineD3DBaseTextureImpl_SetPrivateData,
284     IWineD3DBaseTextureImpl_GetPrivateData,
285     IWineD3DBaseTextureImpl_FreePrivateData,
286     IWineD3DBaseTextureImpl_SetPriority,
287     IWineD3DBaseTextureImpl_GetPriority,
288     IWineD3DBaseTextureImpl_PreLoad,
289     IWineD3DBaseTextureImpl_GetType,
290     
291     /*IWineD3DBaseTexture*/
292     IWineD3DBaseTextureImpl_SetLOD,
293     IWineD3DBaseTextureImpl_GetLOD,
294     IWineD3DBaseTextureImpl_GetLevelCount,
295     IWineD3DBaseTextureImpl_SetAutoGenFilterType,
296     IWineD3DBaseTextureImpl_GetAutoGenFilterType,
297     IWineD3DBaseTextureImpl_GenerateMipSubLevels,
298     IWineD3DBaseTextureImpl_SetDirty,
299     IWineD3DBaseTextureImpl_GetDirty,
300     /* internal */
301     IWineD3DBaseTextureImpl_BindTexture,
302     IWineD3DBaseTextureImpl_UnBindTexture,
303     IWineD3DBaseTextureImpl_GetTextureDimensions
304
305 };