ntoskrnel.exe: Better match the PSDK types and fix the winapi_check warnings.
[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 This->resource.wineD3DDevice->adapter->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     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
100
101     TRACE("(%p) : textureName(%d)\n", This, This->baseTexture.textureName);
102     if (This->baseTexture.textureName != 0) {
103         ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
104         ENTER_GL();
105         TRACE("(%p) : Deleting texture %d\n", This, This->baseTexture.textureName);
106         glDeleteTextures(1, &This->baseTexture.textureName);
107         LEAVE_GL();
108     }
109     IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
110 }
111
112 /* ****************************************************
113    IWineD3DBaseTexture IWineD3DResource parts follow
114    **************************************************** */
115 HRESULT WINAPI IWineD3DBaseTextureImpl_GetDevice(IWineD3DBaseTexture *iface, IWineD3DDevice** ppDevice) {
116     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
117 }
118
119 HRESULT WINAPI IWineD3DBaseTextureImpl_SetPrivateData(IWineD3DBaseTexture *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
120     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
121 }
122
123 HRESULT WINAPI IWineD3DBaseTextureImpl_GetPrivateData(IWineD3DBaseTexture *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
124     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
125 }
126
127 HRESULT WINAPI IWineD3DBaseTextureImpl_FreePrivateData(IWineD3DBaseTexture *iface, REFGUID refguid) {
128     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
129 }
130
131 DWORD    WINAPI        IWineD3DBaseTextureImpl_SetPriority(IWineD3DBaseTexture *iface, DWORD PriorityNew) {
132     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
133 }
134
135 DWORD    WINAPI        IWineD3DBaseTextureImpl_GetPriority(IWineD3DBaseTexture *iface) {
136     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
137 }
138
139 void     WINAPI        IWineD3DBaseTextureImpl_PreLoad(IWineD3DBaseTexture *iface) {
140     IWineD3DResourceImpl_PreLoad((IWineD3DResource *)iface);
141 }
142
143 WINED3DRESOURCETYPE WINAPI IWineD3DBaseTextureImpl_GetType(IWineD3DBaseTexture *iface) {
144     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
145 }
146
147 HRESULT WINAPI IWineD3DBaseTextureImpl_GetParent(IWineD3DBaseTexture *iface, IUnknown **pParent) {
148     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
149 }
150
151 /* ******************************************************
152    IWineD3DBaseTexture IWineD3DBaseTexture parts follow
153    ****************************************************** */
154
155 /* There is no OpenGL equivilent of setLOD, getLOD, all they do it priortise testure loading
156  * so just pretend that they work unless something really needs a failure. */
157 DWORD WINAPI IWineD3DBaseTextureImpl_SetLOD(IWineD3DBaseTexture *iface, DWORD LODNew) {
158     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
159
160     if (This->resource.pool != WINED3DPOOL_MANAGED) {
161         return  WINED3DERR_INVALIDCALL;
162     }
163
164     if(LODNew >= This->baseTexture.levels)
165         LODNew = This->baseTexture.levels - 1;
166      This->baseTexture.LOD = LODNew;
167
168     TRACE("(%p) : set bogus LOD to %d\n", This, This->baseTexture.LOD);
169
170     return This->baseTexture.LOD;
171 }
172
173 DWORD WINAPI IWineD3DBaseTextureImpl_GetLOD(IWineD3DBaseTexture *iface) {
174     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
175
176     if (This->resource.pool != WINED3DPOOL_MANAGED) {
177         return  WINED3DERR_INVALIDCALL;
178     }
179
180     TRACE("(%p) : returning %d\n", This, This->baseTexture.LOD);
181
182     return This->baseTexture.LOD;
183 }
184
185 DWORD WINAPI IWineD3DBaseTextureImpl_GetLevelCount(IWineD3DBaseTexture *iface) {
186     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
187     TRACE("(%p) : returning %d\n", This, This->baseTexture.levels);
188     return This->baseTexture.levels;
189 }
190
191 HRESULT WINAPI IWineD3DBaseTextureImpl_SetAutoGenFilterType(IWineD3DBaseTexture *iface, WINED3DTEXTUREFILTERTYPE FilterType) {
192   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
193
194   if (!(This->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)) {
195       TRACE("(%p) : returning invalid call\n", This);
196       return WINED3DERR_INVALIDCALL;
197   }
198   This->baseTexture.filterType = FilterType;
199   TRACE("(%p) :\n", This);
200   return WINED3D_OK;
201 }
202
203 WINED3DTEXTUREFILTERTYPE WINAPI IWineD3DBaseTextureImpl_GetAutoGenFilterType(IWineD3DBaseTexture *iface) {
204   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
205   FIXME("(%p) : stub\n", This);
206   if (!(This->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)) {
207      return WINED3DTEXF_NONE;
208   }
209   return This->baseTexture.filterType;
210 }
211
212 void WINAPI IWineD3DBaseTextureImpl_GenerateMipSubLevels(IWineD3DBaseTexture *iface) {
213   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
214   /* TODO: implement filters using GL_SGI_generate_mipmaps http://oss.sgi.com/projects/ogl-sample/registry/SGIS/generate_mipmap.txt */
215   FIXME("(%p) : stub\n", This);
216   return ;
217 }
218
219 /* Internal function, No d3d mapping */
220 BOOL WINAPI IWineD3DBaseTextureImpl_SetDirty(IWineD3DBaseTexture *iface, BOOL dirty) {
221     BOOL old;
222     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
223     old = This->baseTexture.dirty;
224     This->baseTexture.dirty = dirty;
225     return old;
226 }
227
228 BOOL WINAPI IWineD3DBaseTextureImpl_GetDirty(IWineD3DBaseTexture *iface) {
229     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
230     return This->baseTexture.dirty;
231 }
232
233 HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) {
234     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
235     HRESULT hr = WINED3D_OK;
236     UINT textureDimensions;
237     BOOL isNewTexture = FALSE;
238     TRACE("(%p) : About to bind texture\n", This);
239
240     textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
241     ENTER_GL();
242     /* Generate a texture name if we don't already have one */
243     if (This->baseTexture.textureName == 0) {
244         glGenTextures(1, &This->baseTexture.textureName);
245         checkGLcall("glGenTextures");
246         TRACE("Generated texture %d\n", This->baseTexture.textureName);
247         if (This->resource.pool == WINED3DPOOL_DEFAULT) {
248             /* Tell opengl to try and keep this texture in video ram (well mostly) */
249             GLclampf tmp;
250             tmp = 0.9f;
251             glPrioritizeTextures(1, &This->baseTexture.textureName, &tmp);
252
253         }
254         /* Initialise the state of the texture object
255         to the openGL defaults, not the directx defaults */
256         This->baseTexture.states[WINED3DTEXSTA_ADDRESSU]      = WINED3DTADDRESS_WRAP;
257         This->baseTexture.states[WINED3DTEXSTA_ADDRESSV]      = WINED3DTADDRESS_WRAP;
258         This->baseTexture.states[WINED3DTEXSTA_ADDRESSW]      = WINED3DTADDRESS_WRAP;
259         This->baseTexture.states[WINED3DTEXSTA_BORDERCOLOR]   = 0;
260         This->baseTexture.states[WINED3DTEXSTA_MAGFILTER]     = WINED3DTEXF_LINEAR;
261         This->baseTexture.states[WINED3DTEXSTA_MINFILTER]     = WINED3DTEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
262         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER]     = WINED3DTEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
263         This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL]   = 0;
264         This->baseTexture.states[WINED3DTEXSTA_MAXANISOTROPY] = 0;
265         This->baseTexture.states[WINED3DTEXSTA_SRGBTEXTURE]   = 0;
266         This->baseTexture.states[WINED3DTEXSTA_ELEMENTINDEX]  = 0;
267         This->baseTexture.states[WINED3DTEXSTA_DMAPOFFSET]    = 0;
268         This->baseTexture.states[WINED3DTEXSTA_TSSADDRESSW]   = WINED3DTADDRESS_WRAP;
269         IWineD3DBaseTexture_SetDirty(iface, TRUE);
270         isNewTexture = TRUE;
271     }
272
273     /* Bind the texture */
274     if (This->baseTexture.textureName != 0) {
275         glBindTexture(textureDimensions, This->baseTexture.textureName);
276         checkGLcall("glBindTexture");
277         if (isNewTexture) {
278             /* For a new texture we have to set the textures levels after binding the texture.
279             * In theory this is all we should ever have to do, but because ATI's drivers are broken, we
280             * also need to set the texture dimensions before the texture is set */
281             TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", This->baseTexture.levels - 1);
282             glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels - 1);
283             checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels)");
284             if(textureDimensions==GL_TEXTURE_CUBE_MAP_ARB) {
285                 /* Cubemaps are always set to clamp, regardeless of the sampler state. */
286                 glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
287                 glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
288                 glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
289             }
290         }
291                 
292     } else { /* this only happened if we've run out of openGL textures */
293         WARN("This texture doesn't have an openGL texture assigned to it\n");
294         hr =  WINED3DERR_INVALIDCALL;
295     }
296
297     LEAVE_GL();
298     return hr;
299 }
300
301 HRESULT WINAPI IWineD3DBaseTextureImpl_UnBindTexture(IWineD3DBaseTexture *iface) {
302     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
303     UINT textureDimensions;
304
305     TRACE("(%p) : About to bind texture\n", This);
306     textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
307
308     ENTER_GL();
309
310     glBindTexture(textureDimensions, 0);
311 #if 0 /* TODO: context manager support */
312      IWineD3DContextManager_PopState(This->contextManager, textureDimensions, ENABLED, NOW /* make sure the state is applied now */);
313 #else
314     glDisable(textureDimensions);
315 #endif
316
317     LEAVE_GL();
318     return WINED3D_OK;
319 }
320
321 UINT WINAPI IWineD3DBaseTextureImpl_GetTextureDimensions(IWineD3DBaseTexture *iface){
322     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
323     FIXME("(%p) : This shouldn't be called\n", This);
324     return WINED3D_OK;
325 }
326
327 static inline GLenum warpLookupType(WINED3DSAMPLERSTATETYPE Type) {
328     switch(Type) {
329     case WINED3DSAMP_ADDRESSU:
330         return GL_TEXTURE_WRAP_S;
331     case WINED3DSAMP_ADDRESSV:
332         return GL_TEXTURE_WRAP_T;
333     case WINED3DSAMP_ADDRESSW:
334         return GL_TEXTURE_WRAP_R;
335     default:
336         FIXME("Unexpected warp type %d\n", Type);
337         return 0;
338     }
339 }
340
341 void WINAPI IWineD3DBaseTextureImpl_ApplyStateChanges(IWineD3DBaseTexture *iface,
342                                     const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1],
343                                     const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) {
344     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
345     int i;
346     DWORD *state = This->baseTexture.states;
347     GLint textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
348     IWineD3DBaseTexture_PreLoad(iface);
349     /* run through a couple of loops and apply and states that are different */
350     /* this will reduce the number of texture state changes to an absolute minimum
351     for multi-parameter states we  pickup the first one that changes, work out the correct values for the other states
352     and set all the states that we've just applied to their new values */
353
354     for (i = 0 ;textureObjectSamplerStates[i].state != -1; i++) {
355         if (*state != samplerStates[textureObjectSamplerStates[i].state]) {
356             /* apply the state */
357             TRACE("(%p) : Changing state %u from %d to %d\n", This, i, *state , samplerStates[textureObjectSamplerStates[i].state]);
358             switch (textureObjectSamplerStates[i].function) {
359             case WINED3DSAMP_ADDRESSU:
360             case WINED3DSAMP_ADDRESSV: /* fall through */
361             case WINED3DSAMP_ADDRESSW: /* fall through */
362                 *state = samplerStates[textureObjectSamplerStates[i].state];
363                 if (*state < minLookup[WINELOOKUP_WARPPARAM] || *state > maxLookup[WINELOOKUP_WARPPARAM]) {
364                     FIXME("Unrecognized or unsupported WINED3DTADDRESS_* value %d, state %d\n", *state, textureObjectSamplerStates[i].function);
365                 } else {
366                     GLint wrapParm;
367                     if(textureDimensions==GL_TEXTURE_CUBE_MAP_ARB) {
368                         /* Cubemaps are always set to clamp, regardeless of the sampler state. */
369                         wrapParm = GL_CLAMP_TO_EDGE;
370                     } else {
371                         wrapParm = stateLookup[WINELOOKUP_WARPPARAM][*state - minLookup[WINELOOKUP_WARPPARAM]];
372                     }
373                     TRACE("Setting WRAP_R to %d for %x\n", wrapParm, textureDimensions);
374                     glTexParameteri(textureDimensions, warpLookupType(textureObjectSamplerStates[i].function), wrapParm);
375                     checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
376                 }
377             break;
378             case WINED3DSAMP_BORDERCOLOR:
379             {
380                 float col[4];
381                 *state = samplerStates[textureObjectSamplerStates[i].state];
382                 D3DCOLORTOGLFLOAT4(*state, col);
383                 TRACE("Setting border color for %u to %x\n", textureDimensions, *state);
384                 glTexParameterfv(textureDimensions, GL_TEXTURE_BORDER_COLOR, &col[0]);
385                 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
386             }
387             break;
388             case WINED3DSAMP_MAGFILTER:
389                 {
390                     GLint glValue;
391                     *state = samplerStates[textureObjectSamplerStates[i].state];
392                     if (*state < minLookup[WINELOOKUP_MAGFILTER] || *state > maxLookup[WINELOOKUP_MAGFILTER]) {
393                         FIXME("Unrecognized or unsupported MAGFILTER* value %d, state %d\n", *state, textureObjectSamplerStates[i].function);
394                     }
395                     glValue = stateLookup[WINELOOKUP_MAGFILTER][*state - minLookup[WINELOOKUP_MAGFILTER]];
396                     TRACE("ValueMAG=%d setting MAGFILTER to %x\n", *state, glValue);
397                     glTexParameteri(textureDimensions, GL_TEXTURE_MAG_FILTER, glValue);
398                 /* 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. */
399                     if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && WINED3DTEXF_ANISOTROPIC == *state) {
400                         glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, samplerStates[WINED3DSAMP_MAXANISOTROPY]);
401                     }
402                 }
403             break;
404
405             case WINED3DSAMP_MINFILTER:
406             case WINED3DSAMP_MAXMIPLEVEL:
407             case WINED3DSAMP_MIPFILTER: /* fall through */
408                 {
409                     GLint glValue;
410
411                     This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = samplerStates[WINED3DSAMP_MIPFILTER];
412                     This->baseTexture.states[WINED3DTEXSTA_MINFILTER] = samplerStates[WINED3DSAMP_MINFILTER];
413                     This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL] = samplerStates[WINED3DSAMP_MAXMIPLEVEL];
414
415                     *state = samplerStates[textureObjectSamplerStates[i].state];
416                     if (This->baseTexture.states[WINED3DTEXSTA_MINFILTER] < WINED3DTEXF_NONE ||
417                         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] < WINED3DTEXF_NONE ||
418                         This->baseTexture.states[WINED3DTEXSTA_MINFILTER] > WINED3DTEXF_ANISOTROPIC ||
419                         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] > WINED3DTEXF_LINEAR)
420                     {
421
422                         FIXME("Unrecognized or unsupported D3DSAMP_MINFILTER value %d, state %d D3DSAMP_MIPFILTER value %d, state %d\n",
423                                 This->baseTexture.states[WINED3DTEXSTA_MINFILTER],
424                                 textureObjectSamplerStates[WINED3DTEXSTA_MINFILTER].function,
425                                 This->baseTexture.states[WINED3DTEXSTA_MIPFILTER],
426                                 textureObjectSamplerStates[WINED3DTEXSTA_MIPFILTER].function);
427                     }
428                     glValue = minMipLookup[min(max(This->baseTexture.states[WINED3DTEXSTA_MINFILTER],WINED3DTEXF_NONE), WINED3DTEXF_ANISOTROPIC)]
429                                                 [min(max(This->baseTexture.states[WINED3DTEXSTA_MIPFILTER],WINED3DTEXF_NONE), WINED3DTEXF_LINEAR)];
430
431                     TRACE("ValueMIN=%d, ValueMIP=%d, setting MINFILTER to %x\n", 
432                             This->baseTexture.states[WINED3DTEXSTA_MINFILTER], 
433                             This->baseTexture.states[WINED3DTEXSTA_MIPFILTER], glValue);
434                     glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, glValue);
435                     checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
436
437                     if(This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] == WINED3DTEXF_NONE) {
438                         glValue = 0;
439                     } else if(This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL] >= This->baseTexture.levels) {
440                         glValue = This->baseTexture.levels - 1;
441                     } else {
442                         glValue = This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL];
443                     }
444                     glTexParameteri(textureDimensions, GL_TEXTURE_BASE_LEVEL, glValue);
445                 }
446             break;
447             break;
448             case WINED3DSAMP_MAXANISOTROPY:
449                 *state = samplerStates[textureObjectSamplerStates[i].state];
450                 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
451                     glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT,  *state);
452                     checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
453                 } else {
454                     WARN("Unsupported in local OpenGL implementation: glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT\n");
455                 }
456             break;
457             case WINED3DFUNC_UNIMPLEMENTED: /* unimplemented */
458                 TRACE("(%p) : stub\n", This);
459                 *state = samplerStates[textureObjectSamplerStates[i].state];
460             break;
461             case WINED3DFUNC_NOTSUPPORTED: /* nop */
462                 TRACE("(%p) : %s function is not supported by this opengl implementation\n", This, "unknown" /* TODO: replace with debug_blah... */);
463                 *state = samplerStates[textureObjectSamplerStates[i].state];
464             break;
465             }
466         }
467         state++;
468     }
469 }
470
471
472 static const IWineD3DBaseTextureVtbl IWineD3DBaseTexture_Vtbl =
473 {
474     /* IUnknown */
475     IWineD3DBaseTextureImpl_QueryInterface,
476     IWineD3DBaseTextureImpl_AddRef,
477     IWineD3DBaseTextureImpl_Release,
478     /* IWineD3DResource */
479     IWineD3DBaseTextureImpl_GetParent,
480     IWineD3DBaseTextureImpl_GetDevice,
481     IWineD3DBaseTextureImpl_SetPrivateData,
482     IWineD3DBaseTextureImpl_GetPrivateData,
483     IWineD3DBaseTextureImpl_FreePrivateData,
484     IWineD3DBaseTextureImpl_SetPriority,
485     IWineD3DBaseTextureImpl_GetPriority,
486     IWineD3DBaseTextureImpl_PreLoad,
487     IWineD3DBaseTextureImpl_GetType,
488     /*IWineD3DBaseTexture*/
489     IWineD3DBaseTextureImpl_SetLOD,
490     IWineD3DBaseTextureImpl_GetLOD,
491     IWineD3DBaseTextureImpl_GetLevelCount,
492     IWineD3DBaseTextureImpl_SetAutoGenFilterType,
493     IWineD3DBaseTextureImpl_GetAutoGenFilterType,
494     IWineD3DBaseTextureImpl_GenerateMipSubLevels,
495     IWineD3DBaseTextureImpl_SetDirty,
496     IWineD3DBaseTextureImpl_GetDirty,
497     /* internal */
498     IWineD3DBaseTextureImpl_BindTexture,
499     IWineD3DBaseTextureImpl_UnBindTexture,
500     IWineD3DBaseTextureImpl_GetTextureDimensions,
501     IWineD3DBaseTextureImpl_ApplyStateChanges
502
503 };