wined3d: Light parameter fixes.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wined3d_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
27 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
28
29 static const Wined3dTextureStateMap textureObjectSamplerStates[]  = {
30     {WINED3DSAMP_ADDRESSU,      WINED3DSAMP_ADDRESSU},
31     {WINED3DSAMP_ADDRESSV,      WINED3DSAMP_ADDRESSV},
32     {WINED3DSAMP_ADDRESSW,      WINED3DSAMP_ADDRESSW},
33 /* NOTE: Sometimes it's a good idea to disable the setting of border colour, e.g. Axis and Allies */
34     {WINED3DSAMP_BORDERCOLOR,   WINED3DFUNC_NOTSUPPORTED/* WINED3DSAMP_BORDERCOLOR */},
35     {WINED3DSAMP_MAGFILTER,     WINED3DSAMP_MAGFILTER},
36     {WINED3DSAMP_MINFILTER,     WINED3DSAMP_MINFILTER},
37     {WINED3DSAMP_MIPFILTER,     WINED3DSAMP_MIPFILTER},
38 /* applies to the texture unit
39     WINED3DSAMP_MIPMAPLODBIAS, WINED3DSAMP_MIPMAPLODBIAS,
40 */
41     {WINED3DSAMP_MAXMIPLEVEL,   WINED3DSAMP_MAXMIPLEVEL},
42 #if 0
43     {WINED3DSAMP_MAXANISOTROPY, GL_SUPPORTED(EXT_TEXTURE_FILTER_ANISOTROPIC) ? WINED3DSAMP_MAXANISOTROPY : WINED3DFUNC_NOTSUPPORTED},
44 #else
45     {WINED3DSAMP_MAXANISOTROPY, WINED3DSAMP_MAXANISOTROPY},
46 #endif
47     {WINED3DSAMP_SRGBTEXTURE,   WINED3DFUNC_UNIMPLEMENTED},
48     {WINED3DSAMP_ELEMENTINDEX,  WINED3DFUNC_UNIMPLEMENTED},
49     {WINED3DSAMP_DMAPOFFSET,    WINED3DFUNC_UNIMPLEMENTED},
50     {-1, 0}
51 };
52
53 static const Wined3dTextureStateMap textureObjectTextureStates[] = {
54     {WINED3DTSS_ADDRESSW , WINED3DTSS_ADDRESSW},
55     {-1, 0}
56 };
57
58 /* *******************************************
59    IWineD3DBaseTexture IUnknown parts follow
60    ******************************************* */
61 HRESULT WINAPI IWineD3DBaseTextureImpl_QueryInterface(IWineD3DBaseTexture *iface, REFIID riid, LPVOID *ppobj)
62 {
63     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
64     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
65     if (IsEqualGUID(riid, &IID_IUnknown)
66         || IsEqualGUID(riid, &IID_IWineD3DBase)
67         || IsEqualGUID(riid, &IID_IWineD3DResource)
68         || IsEqualGUID(riid, &IID_IWineD3DBaseTexture)) {
69         IUnknown_AddRef(iface);
70         *ppobj = This;
71         return S_OK;
72     }
73     *ppobj = NULL;
74     return E_NOINTERFACE;
75 }
76
77 ULONG WINAPI IWineD3DBaseTextureImpl_AddRef(IWineD3DBaseTexture *iface) {
78     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
79     ULONG ref = InterlockedIncrement(&This->resource.ref);
80
81     TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1);
82     return ref;
83 }
84
85 ULONG WINAPI IWineD3DBaseTextureImpl_Release(IWineD3DBaseTexture *iface) {
86     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
87     ULONG ref = InterlockedDecrement(&This->resource.ref);
88     TRACE("(%p) : Releasing from %d\n", This, ref + 1);
89     if (ref == 0) {
90         IWineD3DBaseTextureImpl_CleanUp(iface);
91         HeapFree(GetProcessHeap(), 0, This);
92     }
93     return ref;
94 }
95
96 /* class static */
97 void IWineD3DBaseTextureImpl_CleanUp(IWineD3DBaseTexture *iface) {
98     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
99     TRACE("(%p) : textureName(%d)\n", This, This->baseTexture.textureName);
100     if (This->baseTexture.textureName != 0) {
101         ENTER_GL();
102         TRACE("(%p) : Deleting texture %d\n", This, This->baseTexture.textureName);
103         glDeleteTextures(1, &This->baseTexture.textureName);
104         LEAVE_GL();
105     }
106     IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
107 }
108
109 /* ****************************************************
110    IWineD3DBaseTexture IWineD3DResource parts follow
111    **************************************************** */
112 HRESULT WINAPI IWineD3DBaseTextureImpl_GetDevice(IWineD3DBaseTexture *iface, IWineD3DDevice** ppDevice) {
113     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
114 }
115
116 HRESULT WINAPI IWineD3DBaseTextureImpl_SetPrivateData(IWineD3DBaseTexture *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
117     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
118 }
119
120 HRESULT WINAPI IWineD3DBaseTextureImpl_GetPrivateData(IWineD3DBaseTexture *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
121     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
122 }
123
124 HRESULT WINAPI IWineD3DBaseTextureImpl_FreePrivateData(IWineD3DBaseTexture *iface, REFGUID refguid) {
125     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
126 }
127
128 DWORD    WINAPI        IWineD3DBaseTextureImpl_SetPriority(IWineD3DBaseTexture *iface, DWORD PriorityNew) {
129     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
130 }
131
132 DWORD    WINAPI        IWineD3DBaseTextureImpl_GetPriority(IWineD3DBaseTexture *iface) {
133     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
134 }
135
136 void     WINAPI        IWineD3DBaseTextureImpl_PreLoad(IWineD3DBaseTexture *iface) {
137     return IWineD3DResourceImpl_PreLoad((IWineD3DResource *)iface);
138 }
139
140 WINED3DRESOURCETYPE WINAPI IWineD3DBaseTextureImpl_GetType(IWineD3DBaseTexture *iface) {
141     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
142 }
143
144 HRESULT WINAPI IWineD3DBaseTextureImpl_GetParent(IWineD3DBaseTexture *iface, IUnknown **pParent) {
145     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
146 }
147
148 /* ******************************************************
149    IWineD3DBaseTexture IWineD3DBaseTexture parts follow
150    ****************************************************** */
151
152 /* There is no OpenGL equivilent of setLOD, getLOD, all they do it priortise testure loading
153  * so just pretend that they work unless something really needs a failure. */
154 DWORD WINAPI IWineD3DBaseTextureImpl_SetLOD(IWineD3DBaseTexture *iface, DWORD LODNew) {
155     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
156
157     if (This->resource.pool != WINED3DPOOL_MANAGED) {
158         return  WINED3DERR_INVALIDCALL;
159     }
160
161     if(LODNew >= This->baseTexture.levels)
162         LODNew = This->baseTexture.levels - 1;
163      This->baseTexture.LOD = LODNew;
164
165     TRACE("(%p) : set bogus LOD to %d\n", This, This->baseTexture.LOD);
166
167     return This->baseTexture.LOD;
168 }
169
170 DWORD WINAPI IWineD3DBaseTextureImpl_GetLOD(IWineD3DBaseTexture *iface) {
171     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
172
173     if (This->resource.pool != WINED3DPOOL_MANAGED) {
174         return  WINED3DERR_INVALIDCALL;
175     }
176
177     TRACE("(%p) : returning %d\n", This, This->baseTexture.LOD);
178
179     return This->baseTexture.LOD;
180 }
181
182 DWORD WINAPI IWineD3DBaseTextureImpl_GetLevelCount(IWineD3DBaseTexture *iface) {
183     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
184     TRACE("(%p) : returning %d\n", This, This->baseTexture.levels);
185     return This->baseTexture.levels;
186 }
187
188 HRESULT WINAPI IWineD3DBaseTextureImpl_SetAutoGenFilterType(IWineD3DBaseTexture *iface, WINED3DTEXTUREFILTERTYPE FilterType) {
189   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
190
191   if (!(This->baseTexture.usage & WINED3DUSAGE_AUTOGENMIPMAP)) {
192       TRACE("(%p) : returning invalid call\n", This);
193       return WINED3DERR_INVALIDCALL;
194   }
195   This->baseTexture.filterType = FilterType;
196   TRACE("(%p) :\n", This);
197   return WINED3D_OK;
198 }
199
200 WINED3DTEXTUREFILTERTYPE WINAPI IWineD3DBaseTextureImpl_GetAutoGenFilterType(IWineD3DBaseTexture *iface) {
201   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
202   FIXME("(%p) : stub\n", This);
203   if (!(This->baseTexture.usage & WINED3DUSAGE_AUTOGENMIPMAP)) {
204      return WINED3DTEXF_NONE;
205   }
206   return This->baseTexture.filterType;
207 }
208
209 void WINAPI IWineD3DBaseTextureImpl_GenerateMipSubLevels(IWineD3DBaseTexture *iface) {
210   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
211   /* TODO: implement filters using GL_SGI_generate_mipmaps http://oss.sgi.com/projects/ogl-sample/registry/SGIS/generate_mipmap.txt */
212   FIXME("(%p) : stub\n", This);
213   return ;
214 }
215
216 /* Internal function, No d3d mapping */
217 BOOL WINAPI IWineD3DBaseTextureImpl_SetDirty(IWineD3DBaseTexture *iface, BOOL dirty) {
218     BOOL old;
219     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
220     old = This->baseTexture.dirty;
221     This->baseTexture.dirty = dirty;
222     return old;
223 }
224
225 BOOL WINAPI IWineD3DBaseTextureImpl_GetDirty(IWineD3DBaseTexture *iface) {
226     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
227     return This->baseTexture.dirty;
228 }
229
230 HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) {
231     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
232     HRESULT hr = WINED3D_OK;
233     UINT textureDimensions;
234     BOOL isNewTexture = FALSE;
235     TRACE("(%p) : About to bind texture\n", This);
236
237     textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
238     ENTER_GL();
239
240     /* Generate a texture name if we don't already have one */
241     if (This->baseTexture.textureName == 0) {
242         glGenTextures(1, &This->baseTexture.textureName);
243         checkGLcall("glGenTextures");
244         TRACE("Generated texture %d\n", This->baseTexture.textureName);
245         if (This->resource.pool == WINED3DPOOL_DEFAULT) {
246             /* Tell opengl to try and keep this texture in video ram (well mostly) */
247             GLclampf tmp;
248             tmp = 0.9f;
249             glPrioritizeTextures(1, &This->baseTexture.textureName, &tmp);
250
251         }
252         /* Initialise the state of the texture object
253         to the openGL defaults, not the directx defaults */
254         This->baseTexture.states[WINED3DTEXSTA_ADDRESSU]      = WINED3DTADDRESS_WRAP;
255         This->baseTexture.states[WINED3DTEXSTA_ADDRESSV]      = WINED3DTADDRESS_WRAP;
256         This->baseTexture.states[WINED3DTEXSTA_ADDRESSW]      = WINED3DTADDRESS_WRAP;
257         This->baseTexture.states[WINED3DTEXSTA_BORDERCOLOR]   = 0;
258         This->baseTexture.states[WINED3DTEXSTA_MAGFILTER]     = WINED3DTEXF_LINEAR;
259         This->baseTexture.states[WINED3DTEXSTA_MINFILTER]     = WINED3DTEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
260         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER]     = WINED3DTEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
261         This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL]   = 0;
262         This->baseTexture.states[WINED3DTEXSTA_MAXANISOTROPY] = 0;
263         This->baseTexture.states[WINED3DTEXSTA_SRGBTEXTURE]   = 0;
264         This->baseTexture.states[WINED3DTEXSTA_ELEMENTINDEX]  = 0;
265         This->baseTexture.states[WINED3DTEXSTA_DMAPOFFSET]    = 0;
266         This->baseTexture.states[WINED3DTEXSTA_TSSADDRESSW]   = WINED3DTADDRESS_WRAP;
267         IWineD3DBaseTexture_SetDirty(iface, TRUE);
268         isNewTexture = TRUE;
269     }
270
271     /* Bind the texture */
272     if (This->baseTexture.textureName != 0) {
273         glBindTexture(textureDimensions, This->baseTexture.textureName);
274         checkGLcall("glBindTexture");
275         if (isNewTexture) {
276             /* For a new texture we have to set the textures levels after binding the texture.
277             * In theory this is all we should ever have to do, but because ATI's drivers are broken, we
278             * also need to set the texture dimensions before the texture is set */
279             TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", This->baseTexture.levels - 1);
280             glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels - 1);
281             checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels)");
282         }
283                 
284     } else { /* this only happened if we've run out of openGL textures */
285         WARN("This texture doesn't have an openGL texture assigned to it\n");
286         hr =  WINED3DERR_INVALIDCALL;
287     }
288
289     LEAVE_GL();
290     return hr;
291 }
292
293 HRESULT WINAPI IWineD3DBaseTextureImpl_UnBindTexture(IWineD3DBaseTexture *iface) {
294     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
295     UINT textureDimensions;
296
297     TRACE("(%p) : About to bind texture\n", This);
298     textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
299
300     ENTER_GL();
301
302     glBindTexture(textureDimensions, 0);
303 #if 0 /* TODO: context manager support */
304      IWineD3DContextManager_PopState(This->contextManager, textureDimensions, ENABLED, NOW /* make sure the state is applied now */);
305 #else
306     glDisable(textureDimensions);
307 #endif
308
309     LEAVE_GL();
310     return WINED3D_OK;
311 }
312
313 UINT WINAPI IWineD3DBaseTextureImpl_GetTextureDimensions(IWineD3DBaseTexture *iface){
314     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
315     FIXME("(%p) : This shouldn't be called\n", This);
316     return WINED3D_OK;
317 }
318
319 static inline GLenum warpLookupType(WINED3DSAMPLERSTATETYPE Type) {
320     switch(Type) {
321     case WINED3DSAMP_ADDRESSU:
322         return GL_TEXTURE_WRAP_S;
323     case WINED3DSAMP_ADDRESSV:
324         return GL_TEXTURE_WRAP_T;
325     case WINED3DSAMP_ADDRESSW:
326         return GL_TEXTURE_WRAP_R;
327     default:
328         FIXME("Unexpected warp type %d\n", Type);
329         return 0;
330     }
331 }
332
333 void WINAPI IWineD3DBaseTextureImpl_ApplyStateChanges(IWineD3DBaseTexture *iface,
334                                     const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1],
335                                     const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) {
336     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
337     int i;
338     DWORD *state = This->baseTexture.states;
339     GLint textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
340     IWineD3DBaseTexture_PreLoad(iface);
341     /* run through a couple of loops and apply and states that are different */
342     /* this will reduce the number of texture state changes to an absolute minimum
343     for multi-parameter states we  pickup the first one that changes, work out the correct values for the other states
344     and set all the states that we've just applied to their new values */
345
346     for (i = 0 ;textureObjectSamplerStates[i].state != -1; i++) {
347         if (*state != samplerStates[textureObjectSamplerStates[i].state]) {
348             /* apply the state */
349             TRACE("(%p) : Changing state %u from %d to %d\n", This, i, *state , samplerStates[textureObjectSamplerStates[i].state]);
350             switch (textureObjectSamplerStates[i].function) {
351             case WINED3DSAMP_ADDRESSU:
352             case WINED3DSAMP_ADDRESSV: /* fall through */
353             case WINED3DSAMP_ADDRESSW: /* fall through */
354                 *state = samplerStates[textureObjectSamplerStates[i].state];
355                 if (*state < minLookup[WINELOOKUP_WARPPARAM] || *state > maxLookup[WINELOOKUP_WARPPARAM]) {
356                     FIXME("Unrecognized or unsupported WINED3DTADDRESS_* value %d, state %d\n", *state, textureObjectSamplerStates[i].function);
357                 } else {
358                     GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][*state - minLookup[WINELOOKUP_WARPPARAM]];
359                     TRACE("Setting WRAP_R to %d for %x\n", wrapParm, textureDimensions);
360                     glTexParameteri(textureDimensions, warpLookupType(textureObjectSamplerStates[i].function), wrapParm);
361                     checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
362                 }
363             break;
364             case WINED3DSAMP_BORDERCOLOR:
365             {
366                 float col[4];
367                 *state = samplerStates[textureObjectSamplerStates[i].state];
368                 D3DCOLORTOGLFLOAT4(*state, col);
369                 TRACE("Setting border color for %u to %x\n", textureDimensions, *state);
370                 glTexParameterfv(textureDimensions, GL_TEXTURE_BORDER_COLOR, &col[0]);
371                 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
372             }
373             break;
374             case WINED3DSAMP_MAGFILTER:
375                 {
376                     GLint glValue;
377                     *state = samplerStates[textureObjectSamplerStates[i].state];
378                     if (*state < minLookup[WINELOOKUP_MAGFILTER] || *state > maxLookup[WINELOOKUP_MAGFILTER]) {
379                         FIXME("Unrecognized or unsupported MAGFILTER* value %d, state %d\n", *state, textureObjectSamplerStates[i].function);
380                     }
381                     glValue = stateLookup[WINELOOKUP_MAGFILTER][*state - minLookup[WINELOOKUP_MAGFILTER]];
382                     TRACE("ValueMAG=%d setting MAGFILTER to %x\n", *state, glValue);
383                     glTexParameteri(textureDimensions, GL_TEXTURE_MAG_FILTER, glValue);
384                 /* We need to reset the Aniotropic filtering state when we change the mag filter to WINED3DTEXF_ANISOTROPIC (this seems a bit weird, check the documentataion to see how it should be switched off. */
385                     if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && WINED3DTEXF_ANISOTROPIC == *state) {
386                         glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, samplerStates[WINED3DSAMP_MAXANISOTROPY]);
387                     }
388                 }
389             break;
390
391             case WINED3DSAMP_MINFILTER:
392                 This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = samplerStates[WINED3DSAMP_MIPFILTER];
393             case WINED3DSAMP_MIPFILTER: /* fall through */
394                 {
395                     GLint glValue;
396                     *state = samplerStates[textureObjectSamplerStates[i].state];
397                     if (This->baseTexture.states[WINED3DTEXSTA_MINFILTER] < WINED3DTEXF_NONE ||
398                         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] < WINED3DTEXF_NONE ||
399                         This->baseTexture.states[WINED3DTEXSTA_MINFILTER] > WINED3DTEXF_ANISOTROPIC ||
400                         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] > WINED3DTEXF_LINEAR)
401                     {
402
403                         FIXME("Unrecognized or unsupported D3DSAMP_MINFILTER value %d, state %d D3DSAMP_MIPFILTER value %d, state %d\n",
404                                 This->baseTexture.states[WINED3DTEXSTA_MINFILTER],
405                                 textureObjectSamplerStates[WINED3DTEXSTA_MINFILTER].function,
406                                 This->baseTexture.states[WINED3DTEXSTA_MIPFILTER],
407                                 textureObjectSamplerStates[WINED3DTEXSTA_MIPFILTER].function);
408                     }
409                     glValue = minMipLookup[min(max(This->baseTexture.states[WINED3DTEXSTA_MINFILTER],WINED3DTEXF_NONE), WINED3DTEXF_ANISOTROPIC)]
410                                                 [min(max(This->baseTexture.states[WINED3DTEXSTA_MIPFILTER],WINED3DTEXF_NONE), WINED3DTEXF_LINEAR)];
411
412                     TRACE("ValueMIN=%d, ValueMIP=%d, setting MINFILTER to %x\n", 
413                             This->baseTexture.states[WINED3DTEXSTA_MINFILTER], 
414                             This->baseTexture.states[WINED3DTEXSTA_MIPFILTER], glValue);
415                     glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, glValue);
416                     checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
417                 }
418             break;
419             case WINED3DSAMP_MAXMIPLEVEL:
420                 *state = samplerStates[textureObjectSamplerStates[i].state];
421                 /**
422                 * Not really the same, but the more apprioprate than nothing
423                 */
424                 glTexParameteri(textureDimensions, GL_TEXTURE_BASE_LEVEL, *state);
425             break;
426             case WINED3DSAMP_MAXANISOTROPY:
427                 *state = samplerStates[textureObjectSamplerStates[i].state];
428                 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
429                     glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT,  *state);
430                     checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
431                 } else {
432                     WARN("Unsupported in local OpenGL implementation: glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT\n");
433                 }
434             break;
435             case WINED3DFUNC_UNIMPLEMENTED: /* unimplemented */
436                 TRACE("(%p) : stub\n", This);
437                 *state = samplerStates[textureObjectSamplerStates[i].state];
438             break;
439             case WINED3DFUNC_NOTSUPPORTED: /* nop */
440                 TRACE("(%p) : %s function is not supported by this opengl implementation\n", This, "unknown" /* TODO: replace with debug_blah... */);
441                 *state = samplerStates[textureObjectSamplerStates[i].state];
442             break;
443             }
444         }
445         state++;
446     }
447 }
448
449
450 static const IWineD3DBaseTextureVtbl IWineD3DBaseTexture_Vtbl =
451 {
452     /* IUnknown */
453     IWineD3DBaseTextureImpl_QueryInterface,
454     IWineD3DBaseTextureImpl_AddRef,
455     IWineD3DBaseTextureImpl_Release,
456     /* IWineD3DResource */
457     IWineD3DBaseTextureImpl_GetParent,
458     IWineD3DBaseTextureImpl_GetDevice,
459     IWineD3DBaseTextureImpl_SetPrivateData,
460     IWineD3DBaseTextureImpl_GetPrivateData,
461     IWineD3DBaseTextureImpl_FreePrivateData,
462     IWineD3DBaseTextureImpl_SetPriority,
463     IWineD3DBaseTextureImpl_GetPriority,
464     IWineD3DBaseTextureImpl_PreLoad,
465     IWineD3DBaseTextureImpl_GetType,
466     /*IWineD3DBaseTexture*/
467     IWineD3DBaseTextureImpl_SetLOD,
468     IWineD3DBaseTextureImpl_GetLOD,
469     IWineD3DBaseTextureImpl_GetLevelCount,
470     IWineD3DBaseTextureImpl_SetAutoGenFilterType,
471     IWineD3DBaseTextureImpl_GetAutoGenFilterType,
472     IWineD3DBaseTextureImpl_GenerateMipSubLevels,
473     IWineD3DBaseTextureImpl_SetDirty,
474     IWineD3DBaseTextureImpl_GetDirty,
475     /* internal */
476     IWineD3DBaseTextureImpl_BindTexture,
477     IWineD3DBaseTextureImpl_UnBindTexture,
478     IWineD3DBaseTextureImpl_GetTextureDimensions,
479     IWineD3DBaseTextureImpl_ApplyStateChanges
480
481 };