kernel32: GlobalMemoryStatusEx: return the size of physical memory + swapsize in...
[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             if(textureDimensions==GL_TEXTURE_CUBE_MAP_ARB) {
283                 /* Cubemaps are always set to clamp, regardeless of the sampler state. */
284                 glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
285                 glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
286                 glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
287             }
288         }
289                 
290     } else { /* this only happened if we've run out of openGL textures */
291         WARN("This texture doesn't have an openGL texture assigned to it\n");
292         hr =  WINED3DERR_INVALIDCALL;
293     }
294
295     LEAVE_GL();
296     return hr;
297 }
298
299 HRESULT WINAPI IWineD3DBaseTextureImpl_UnBindTexture(IWineD3DBaseTexture *iface) {
300     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
301     UINT textureDimensions;
302
303     TRACE("(%p) : About to bind texture\n", This);
304     textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
305
306     ENTER_GL();
307
308     glBindTexture(textureDimensions, 0);
309 #if 0 /* TODO: context manager support */
310      IWineD3DContextManager_PopState(This->contextManager, textureDimensions, ENABLED, NOW /* make sure the state is applied now */);
311 #else
312     glDisable(textureDimensions);
313 #endif
314
315     LEAVE_GL();
316     return WINED3D_OK;
317 }
318
319 UINT WINAPI IWineD3DBaseTextureImpl_GetTextureDimensions(IWineD3DBaseTexture *iface){
320     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
321     FIXME("(%p) : This shouldn't be called\n", This);
322     return WINED3D_OK;
323 }
324
325 static inline GLenum warpLookupType(WINED3DSAMPLERSTATETYPE Type) {
326     switch(Type) {
327     case WINED3DSAMP_ADDRESSU:
328         return GL_TEXTURE_WRAP_S;
329     case WINED3DSAMP_ADDRESSV:
330         return GL_TEXTURE_WRAP_T;
331     case WINED3DSAMP_ADDRESSW:
332         return GL_TEXTURE_WRAP_R;
333     default:
334         FIXME("Unexpected warp type %d\n", Type);
335         return 0;
336     }
337 }
338
339 void WINAPI IWineD3DBaseTextureImpl_ApplyStateChanges(IWineD3DBaseTexture *iface,
340                                     const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1],
341                                     const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) {
342     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
343     int i;
344     DWORD *state = This->baseTexture.states;
345     GLint textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
346     IWineD3DBaseTexture_PreLoad(iface);
347     /* run through a couple of loops and apply and states that are different */
348     /* this will reduce the number of texture state changes to an absolute minimum
349     for multi-parameter states we  pickup the first one that changes, work out the correct values for the other states
350     and set all the states that we've just applied to their new values */
351
352     for (i = 0 ;textureObjectSamplerStates[i].state != -1; i++) {
353         if (*state != samplerStates[textureObjectSamplerStates[i].state]) {
354             /* apply the state */
355             TRACE("(%p) : Changing state %u from %d to %d\n", This, i, *state , samplerStates[textureObjectSamplerStates[i].state]);
356             switch (textureObjectSamplerStates[i].function) {
357             case WINED3DSAMP_ADDRESSU:
358             case WINED3DSAMP_ADDRESSV: /* fall through */
359             case WINED3DSAMP_ADDRESSW: /* fall through */
360                 *state = samplerStates[textureObjectSamplerStates[i].state];
361                 if (*state < minLookup[WINELOOKUP_WARPPARAM] || *state > maxLookup[WINELOOKUP_WARPPARAM]) {
362                     FIXME("Unrecognized or unsupported WINED3DTADDRESS_* value %d, state %d\n", *state, textureObjectSamplerStates[i].function);
363                 } else {
364                     GLint wrapParm;
365                     if(textureDimensions==GL_TEXTURE_CUBE_MAP_ARB) {
366                         /* Cubemaps are always set to clamp, regardeless of the sampler state. */
367                         wrapParm = GL_CLAMP_TO_EDGE;
368                     } else {
369                         wrapParm = stateLookup[WINELOOKUP_WARPPARAM][*state - minLookup[WINELOOKUP_WARPPARAM]];
370                     }
371                     TRACE("Setting WRAP_R to %d for %x\n", wrapParm, textureDimensions);
372                     glTexParameteri(textureDimensions, warpLookupType(textureObjectSamplerStates[i].function), wrapParm);
373                     checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
374                 }
375             break;
376             case WINED3DSAMP_BORDERCOLOR:
377             {
378                 float col[4];
379                 *state = samplerStates[textureObjectSamplerStates[i].state];
380                 D3DCOLORTOGLFLOAT4(*state, col);
381                 TRACE("Setting border color for %u to %x\n", textureDimensions, *state);
382                 glTexParameterfv(textureDimensions, GL_TEXTURE_BORDER_COLOR, &col[0]);
383                 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
384             }
385             break;
386             case WINED3DSAMP_MAGFILTER:
387                 {
388                     GLint glValue;
389                     *state = samplerStates[textureObjectSamplerStates[i].state];
390                     if (*state < minLookup[WINELOOKUP_MAGFILTER] || *state > maxLookup[WINELOOKUP_MAGFILTER]) {
391                         FIXME("Unrecognized or unsupported MAGFILTER* value %d, state %d\n", *state, textureObjectSamplerStates[i].function);
392                     }
393                     glValue = stateLookup[WINELOOKUP_MAGFILTER][*state - minLookup[WINELOOKUP_MAGFILTER]];
394                     TRACE("ValueMAG=%d setting MAGFILTER to %x\n", *state, glValue);
395                     glTexParameteri(textureDimensions, GL_TEXTURE_MAG_FILTER, glValue);
396                 /* 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. */
397                     if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && WINED3DTEXF_ANISOTROPIC == *state) {
398                         glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, samplerStates[WINED3DSAMP_MAXANISOTROPY]);
399                     }
400                 }
401             break;
402
403             case WINED3DSAMP_MINFILTER:
404                 This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = samplerStates[WINED3DSAMP_MIPFILTER];
405             case WINED3DSAMP_MIPFILTER: /* fall through */
406                 {
407                     GLint glValue;
408                     *state = samplerStates[textureObjectSamplerStates[i].state];
409                     if (This->baseTexture.states[WINED3DTEXSTA_MINFILTER] < WINED3DTEXF_NONE ||
410                         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] < WINED3DTEXF_NONE ||
411                         This->baseTexture.states[WINED3DTEXSTA_MINFILTER] > WINED3DTEXF_ANISOTROPIC ||
412                         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] > WINED3DTEXF_LINEAR)
413                     {
414
415                         FIXME("Unrecognized or unsupported D3DSAMP_MINFILTER value %d, state %d D3DSAMP_MIPFILTER value %d, state %d\n",
416                                 This->baseTexture.states[WINED3DTEXSTA_MINFILTER],
417                                 textureObjectSamplerStates[WINED3DTEXSTA_MINFILTER].function,
418                                 This->baseTexture.states[WINED3DTEXSTA_MIPFILTER],
419                                 textureObjectSamplerStates[WINED3DTEXSTA_MIPFILTER].function);
420                     }
421                     glValue = minMipLookup[min(max(This->baseTexture.states[WINED3DTEXSTA_MINFILTER],WINED3DTEXF_NONE), WINED3DTEXF_ANISOTROPIC)]
422                                                 [min(max(This->baseTexture.states[WINED3DTEXSTA_MIPFILTER],WINED3DTEXF_NONE), WINED3DTEXF_LINEAR)];
423
424                     TRACE("ValueMIN=%d, ValueMIP=%d, setting MINFILTER to %x\n", 
425                             This->baseTexture.states[WINED3DTEXSTA_MINFILTER], 
426                             This->baseTexture.states[WINED3DTEXSTA_MIPFILTER], glValue);
427                     glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, glValue);
428                     checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
429                 }
430             break;
431             case WINED3DSAMP_MAXMIPLEVEL:
432                 *state = samplerStates[textureObjectSamplerStates[i].state];
433                 /**
434                 * Not really the same, but the more apprioprate than nothing
435                 */
436                 glTexParameteri(textureDimensions, GL_TEXTURE_BASE_LEVEL, *state);
437             break;
438             case WINED3DSAMP_MAXANISOTROPY:
439                 *state = samplerStates[textureObjectSamplerStates[i].state];
440                 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
441                     glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT,  *state);
442                     checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
443                 } else {
444                     WARN("Unsupported in local OpenGL implementation: glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT\n");
445                 }
446             break;
447             case WINED3DFUNC_UNIMPLEMENTED: /* unimplemented */
448                 TRACE("(%p) : stub\n", This);
449                 *state = samplerStates[textureObjectSamplerStates[i].state];
450             break;
451             case WINED3DFUNC_NOTSUPPORTED: /* nop */
452                 TRACE("(%p) : %s function is not supported by this opengl implementation\n", This, "unknown" /* TODO: replace with debug_blah... */);
453                 *state = samplerStates[textureObjectSamplerStates[i].state];
454             break;
455             }
456         }
457         state++;
458     }
459 }
460
461
462 static const IWineD3DBaseTextureVtbl IWineD3DBaseTexture_Vtbl =
463 {
464     /* IUnknown */
465     IWineD3DBaseTextureImpl_QueryInterface,
466     IWineD3DBaseTextureImpl_AddRef,
467     IWineD3DBaseTextureImpl_Release,
468     /* IWineD3DResource */
469     IWineD3DBaseTextureImpl_GetParent,
470     IWineD3DBaseTextureImpl_GetDevice,
471     IWineD3DBaseTextureImpl_SetPrivateData,
472     IWineD3DBaseTextureImpl_GetPrivateData,
473     IWineD3DBaseTextureImpl_FreePrivateData,
474     IWineD3DBaseTextureImpl_SetPriority,
475     IWineD3DBaseTextureImpl_GetPriority,
476     IWineD3DBaseTextureImpl_PreLoad,
477     IWineD3DBaseTextureImpl_GetType,
478     /*IWineD3DBaseTexture*/
479     IWineD3DBaseTextureImpl_SetLOD,
480     IWineD3DBaseTextureImpl_GetLOD,
481     IWineD3DBaseTextureImpl_GetLevelCount,
482     IWineD3DBaseTextureImpl_SetAutoGenFilterType,
483     IWineD3DBaseTextureImpl_GetAutoGenFilterType,
484     IWineD3DBaseTextureImpl_GenerateMipSubLevels,
485     IWineD3DBaseTextureImpl_SetDirty,
486     IWineD3DBaseTextureImpl_GetDirty,
487     /* internal */
488     IWineD3DBaseTextureImpl_BindTexture,
489     IWineD3DBaseTextureImpl_UnBindTexture,
490     IWineD3DBaseTextureImpl_GetTextureDimensions,
491     IWineD3DBaseTextureImpl_ApplyStateChanges
492
493 };