wined3d: Add a few more WINED3DFMT formats to be recognized.
[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_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 D3D_OK;
72     }
73     return E_NOINTERFACE;
74 }
75
76 ULONG WINAPI IWineD3DBaseTextureImpl_AddRef(IWineD3DBaseTexture *iface) {
77     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
78     ULONG ref = InterlockedIncrement(&This->resource.ref);
79
80     TRACE("(%p) : AddRef increasing from %ld\n", This,ref - 1);
81     return ref;
82 }
83
84 ULONG WINAPI IWineD3DBaseTextureImpl_Release(IWineD3DBaseTexture *iface) {
85     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
86     ULONG ref = InterlockedDecrement(&This->resource.ref);
87     TRACE("(%p) : Releasing from %ld\n", This, ref + 1);
88     if (ref == 0) {
89         IWineD3DBaseTextureImpl_CleanUp(iface);
90         HeapFree(GetProcessHeap(), 0, This);
91     }
92     return ref;
93 }
94
95 /* class static */
96 void IWineD3DBaseTextureImpl_CleanUp(IWineD3DBaseTexture *iface) {
97     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
98     TRACE("(%p) : textureName(%d)\n", This, This->baseTexture.textureName);
99     if (This->baseTexture.textureName != 0) {
100         ENTER_GL();
101         TRACE("(%p) : Deleting texture %d\n", This, This->baseTexture.textureName);
102         glDeleteTextures(1, &This->baseTexture.textureName);
103         LEAVE_GL();
104     }
105     IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
106 }
107
108 /* ****************************************************
109    IWineD3DBaseTexture IWineD3DResource parts follow
110    **************************************************** */
111 HRESULT WINAPI IWineD3DBaseTextureImpl_GetDevice(IWineD3DBaseTexture *iface, IWineD3DDevice** ppDevice) {
112     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
113 }
114
115 HRESULT WINAPI IWineD3DBaseTextureImpl_SetPrivateData(IWineD3DBaseTexture *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
116     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
117 }
118
119 HRESULT WINAPI IWineD3DBaseTextureImpl_GetPrivateData(IWineD3DBaseTexture *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
120     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
121 }
122
123 HRESULT WINAPI IWineD3DBaseTextureImpl_FreePrivateData(IWineD3DBaseTexture *iface, REFGUID refguid) {
124     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
125 }
126
127 DWORD    WINAPI        IWineD3DBaseTextureImpl_SetPriority(IWineD3DBaseTexture *iface, DWORD PriorityNew) {
128     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
129 }
130
131 DWORD    WINAPI        IWineD3DBaseTextureImpl_GetPriority(IWineD3DBaseTexture *iface) {
132     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
133 }
134
135 void     WINAPI        IWineD3DBaseTextureImpl_PreLoad(IWineD3DBaseTexture *iface) {
136     return IWineD3DResourceImpl_PreLoad((IWineD3DResource *)iface);
137 }
138
139 D3DRESOURCETYPE WINAPI IWineD3DBaseTextureImpl_GetType(IWineD3DBaseTexture *iface) {
140     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
141 }
142
143 HRESULT WINAPI IWineD3DBaseTextureImpl_GetParent(IWineD3DBaseTexture *iface, IUnknown **pParent) {
144     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
145 }
146
147 /* ******************************************************
148    IWineD3DBaseTexture IWineD3DBaseTexture parts follow
149    ****************************************************** */
150
151 /* There is no OpenGL equivilent of setLOD, getLOD, all they do it priortise testure loading
152  * so just pretend that they work unless something really needs a failure. */
153 DWORD WINAPI IWineD3DBaseTextureImpl_SetLOD(IWineD3DBaseTexture *iface, DWORD LODNew) {
154     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
155
156     if (This->resource.pool != D3DPOOL_MANAGED) {
157         return  D3DERR_INVALIDCALL;
158     }
159
160     if(LODNew >= This->baseTexture.levels)
161         LODNew = This->baseTexture.levels - 1;
162      This->baseTexture.LOD = LODNew;
163
164     TRACE("(%p) : set bogus LOD to %d\n", This, This->baseTexture.LOD);
165
166     return This->baseTexture.LOD;
167 }
168
169 DWORD WINAPI IWineD3DBaseTextureImpl_GetLOD(IWineD3DBaseTexture *iface) {
170     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
171
172     if (This->resource.pool != D3DPOOL_MANAGED) {
173         return  D3DERR_INVALIDCALL;
174     }
175
176     TRACE("(%p) : returning %d\n", This, This->baseTexture.LOD);
177
178     return This->baseTexture.LOD;
179 }
180
181 DWORD WINAPI IWineD3DBaseTextureImpl_GetLevelCount(IWineD3DBaseTexture *iface) {
182     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
183     TRACE("(%p) : returning %d\n", This, This->baseTexture.levels);
184     return This->baseTexture.levels;
185 }
186
187 HRESULT WINAPI IWineD3DBaseTextureImpl_SetAutoGenFilterType(IWineD3DBaseTexture *iface, D3DTEXTUREFILTERTYPE FilterType) {
188   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
189
190   if (!(This->baseTexture.usage & D3DUSAGE_AUTOGENMIPMAP)) {
191       TRACE("(%p) : returning invalid call\n", This);
192       return D3DERR_INVALIDCALL;
193   }
194   This->baseTexture.filterType = FilterType;
195   TRACE("(%p) :\n", This);
196   return D3D_OK;
197 }
198
199 D3DTEXTUREFILTERTYPE WINAPI IWineD3DBaseTextureImpl_GetAutoGenFilterType(IWineD3DBaseTexture *iface) {
200   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
201   FIXME("(%p) : stub\n", This);
202   if (!(This->baseTexture.usage & D3DUSAGE_AUTOGENMIPMAP)) {
203      return D3DTEXF_NONE;
204   }
205   return This->baseTexture.filterType;
206   return D3DTEXF_LINEAR; /* default */
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 = D3D_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 #if 0 /* TODO: context manager support */
240      IWineD3DContextManager_PushState(This->contextManager, textureDimensions, ENABLED, NOW /* make sure the state is applied now */);
241 #else
242     glEnable(textureDimensions);
243 #endif
244
245     /* Generate a texture name if we don't already have one */
246     if (This->baseTexture.textureName == 0) {
247         glGenTextures(1, &This->baseTexture.textureName);
248         checkGLcall("glGenTextures");
249         TRACE("Generated texture %d\n", This->baseTexture.textureName);
250         if (This->resource.pool == D3DPOOL_DEFAULT) {
251             /* Tell opengl to try and keep this texture in video ram (well mostly) */
252             GLclampf tmp;
253             tmp = 0.9f;
254             glPrioritizeTextures(1, &This->baseTexture.textureName, &tmp);
255
256         }
257         /* Initialise the state of the texture object
258         to the openGL defaults, not the directx defaults */
259         This->baseTexture.states[WINED3DTEXSTA_ADDRESSU]      = D3DTADDRESS_WRAP;
260         This->baseTexture.states[WINED3DTEXSTA_ADDRESSV]      = D3DTADDRESS_WRAP;
261         This->baseTexture.states[WINED3DTEXSTA_ADDRESSW]      = D3DTADDRESS_WRAP;
262         This->baseTexture.states[WINED3DTEXSTA_BORDERCOLOR]   = 0;
263         This->baseTexture.states[WINED3DTEXSTA_MAGFILTER]     = D3DTEXF_LINEAR;
264         This->baseTexture.states[WINED3DTEXSTA_MINFILTER]     = D3DTEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
265         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER]     = D3DTEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
266         This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL]   = 0;
267         This->baseTexture.states[WINED3DTEXSTA_MAXANISOTROPY] = 0;
268         This->baseTexture.states[WINED3DTEXSTA_SRGBTEXTURE]   = 0;
269         This->baseTexture.states[WINED3DTEXSTA_ELEMENTINDEX]  = 0;
270         This->baseTexture.states[WINED3DTEXSTA_DMAPOFFSET]    = 0;
271         This->baseTexture.states[WINED3DTEXSTA_TSSADDRESSW]   = D3DTADDRESS_WRAP;
272         IWineD3DBaseTexture_SetDirty(iface, TRUE);
273         isNewTexture = TRUE;
274     }
275
276     /* Bind the texture */
277     if (This->baseTexture.textureName != 0) {
278         /* Always need to reset the number of mipmap levels when rebinding as it is
279         a property of the active texture unit, and another texture may have set it
280         to a different value                                                       */
281         if (This->baseTexture.levels > 1) {
282             TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", This->baseTexture.levels - 1);
283             glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels - 1);
284             checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels)");
285         } else {
286             glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
287         }
288         glBindTexture(textureDimensions, This->baseTexture.textureName);
289         checkGLcall("glBindTexture");
290         if (isNewTexture) {
291             /* For a new texture we have to set the textures levels after binding the texture,
292             * in theory this is all we should ever have to dom, but because ATI's drivers are broken we
293             * also need to set the texture dimensins before the texture is is set */
294             TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", This->baseTexture.levels - 1);
295             glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels - 1);
296             checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels)");
297         }
298                 
299     } else { /* this only happened if we've run out of openGL textures */
300         WARN("This texture doesn't have an openGL texture assigned to it\n");
301         hr =  D3DERR_INVALIDCALL;
302     }
303
304     LEAVE_GL();
305     return hr;
306 }
307
308 HRESULT WINAPI IWineD3DBaseTextureImpl_UnBindTexture(IWineD3DBaseTexture *iface) {
309     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
310     UINT textureDimensions;
311
312     TRACE("(%p) : About to bind texture\n", This);
313     textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
314
315     ENTER_GL();
316
317     glBindTexture(textureDimensions, 0);
318 #if 0 /* TODO: context manager support */
319      IWineD3DContextManager_PopState(This->contextManager, textureDimensions, ENABLED, NOW /* make sure the state is applied now */);
320 #else
321     glDisable(textureDimensions);
322 #endif
323
324     LEAVE_GL();
325     return D3D_OK;
326 }
327
328 UINT WINAPI IWineD3DBaseTextureImpl_GetTextureDimensions(IWineD3DBaseTexture *iface){
329     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
330     FIXME("(%p) : This shouldn't be called\n", This);
331     return D3D_OK;
332 }
333
334 static inline GLenum warpLookupType(WINED3DSAMPLERSTATETYPE Type) {
335     switch(Type) {
336     case WINED3DSAMP_ADDRESSU:
337         return GL_TEXTURE_WRAP_S;
338     case WINED3DSAMP_ADDRESSV:
339         return GL_TEXTURE_WRAP_T;
340     case WINED3DSAMP_ADDRESSW:
341         return GL_TEXTURE_WRAP_R;
342     default:
343         FIXME("Unexpected warp type %d\n", Type);
344         return 0;
345     }
346 }
347
348 void WINAPI IWineD3DBaseTextureImpl_ApplyStateChanges(IWineD3DBaseTexture *iface,
349                                     const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1],
350                                     const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) {
351     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
352     int i;
353     DWORD *state = This->baseTexture.states;
354     GLint textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
355     IWineD3DBaseTexture_PreLoad(iface);
356     /* run through a couple of loops and apply and states that are different */
357     /* this will reduce the number of texture state changes to an absolute minimum
358     for multi-parameter states we  pickup the first one that changes, work out the correct values for the other states
359     and set all the states that we've just applied to their new values */
360
361     for (i = 0 ;textureObjectSamplerStates[i].state != -1; i++) {
362         if (*state != samplerStates[textureObjectSamplerStates[i].state]) {
363             /* apply the state */
364             TRACE("(%p) : Changing state %u from %ld to %ld\n", This, i, *state , samplerStates[textureObjectSamplerStates[i].state]);
365             switch (textureObjectSamplerStates[i].function) {
366             case WINED3DSAMP_ADDRESSU:
367             case WINED3DSAMP_ADDRESSV: /* fall through */
368             case WINED3DSAMP_ADDRESSW: /* fall through */
369                 *state = samplerStates[textureObjectSamplerStates[i].state];
370                 if (*state < minLookup[WINELOOKUP_WARPPARAM] || *state > maxLookup[WINELOOKUP_WARPPARAM]) {
371                     FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", *state, textureObjectSamplerStates[i].function);
372                 } else {
373                     GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][*state - minLookup[WINELOOKUP_WARPPARAM]];
374                     TRACE("Setting WRAP_R to %d for %x\n", wrapParm, textureDimensions);
375                     glTexParameteri(textureDimensions, warpLookupType(textureObjectSamplerStates[i].function), wrapParm);
376                     checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
377                 }
378             break;
379             case WINED3DSAMP_BORDERCOLOR:
380             {
381                 float col[4];
382                 *state = samplerStates[textureObjectSamplerStates[i].state];
383                 D3DCOLORTOGLFLOAT4(*state, col);
384                 TRACE("Setting border color for %u to %lx\n", textureDimensions, *state);
385                 glTexParameterfv(textureDimensions, GL_TEXTURE_BORDER_COLOR, &col[0]);
386                 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
387             }
388             break;
389             case WINED3DSAMP_MAGFILTER:
390                 {
391                     GLint glValue;
392                     *state = samplerStates[textureObjectSamplerStates[i].state];
393                     if (*state < minLookup[WINELOOKUP_MAGFILTER] || *state > maxLookup[WINELOOKUP_MAGFILTER]) {
394                         FIXME("Unrecognized or unsupported MAGFILTER* value %ld, state %d\n", *state, textureObjectSamplerStates[i].function);
395                     }
396                     glValue = stateLookup[WINELOOKUP_MAGFILTER][*state - minLookup[WINELOOKUP_MAGFILTER]];
397                     TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", *state, glValue);
398                     glTexParameteri(textureDimensions, GL_TEXTURE_MAG_FILTER, glValue);
399                 /* We need to reset the Aniotropic filtering state when we change the mag filter to D3DTEXF_ANISOTROPIC (this seems a bit weird, check the documentataion to see how it should be switched off. */
400                     if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == *state) {
401                         glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, samplerStates[WINED3DSAMP_MAXANISOTROPY]);
402                     }
403                 }
404             break;
405
406             case WINED3DSAMP_MINFILTER:
407                 This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = samplerStates[WINED3DSAMP_MIPFILTER];
408             case WINED3DSAMP_MIPFILTER: /* fall through */
409                 {
410                     GLint glValue;
411                     *state = samplerStates[textureObjectSamplerStates[i].state];
412                     if (This->baseTexture.states[WINED3DTEXSTA_MINFILTER] < D3DTEXF_NONE ||
413                         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] < D3DTEXF_NONE ||
414                         This->baseTexture.states[WINED3DTEXSTA_MINFILTER] > D3DTEXF_ANISOTROPIC ||
415                         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] > D3DTEXF_LINEAR)
416                     {
417
418                         FIXME("Unrecognized or unsupported D3DSAMP_MINFILTER value %ld, state %d D3DSAMP_MIPFILTER value %ld, state %d\n",
419                                 This->baseTexture.states[WINED3DTEXSTA_MINFILTER],
420                                 textureObjectSamplerStates[WINED3DTEXSTA_MINFILTER].function,
421                                 This->baseTexture.states[WINED3DTEXSTA_MIPFILTER],
422                                 textureObjectSamplerStates[WINED3DTEXSTA_MIPFILTER].function);
423                     }
424                     glValue = minMipLookup[min(max(This->baseTexture.states[WINED3DTEXSTA_MINFILTER],D3DTEXF_NONE), D3DTEXF_ANISOTROPIC)]
425                                                 [min(max(This->baseTexture.states[WINED3DTEXSTA_MIPFILTER],D3DTEXF_NONE), D3DTEXF_LINEAR)];
426
427                     TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", 
428                             This->baseTexture.states[WINED3DTEXSTA_MINFILTER], 
429                             This->baseTexture.states[WINED3DTEXSTA_MIPFILTER], glValue);
430                     glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, glValue);
431                     checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
432                 }
433             break;
434             case WINED3DSAMP_MAXMIPLEVEL:
435                 *state = samplerStates[textureObjectSamplerStates[i].state];
436                 /**
437                 * Not really the same, but the more apprioprate than nothing
438                 */
439                 glTexParameteri(textureDimensions, GL_TEXTURE_BASE_LEVEL, *state);
440             break;
441             case WINED3DSAMP_MAXANISOTROPY:
442                 *state = samplerStates[textureObjectSamplerStates[i].state];
443                 glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT,  *state);
444                 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
445             break;
446             case WINED3DFUNC_UNIMPLEMENTED: /* unimplemented */
447                 TRACE("(%p) : stub\n", This);
448                 *state = samplerStates[textureObjectSamplerStates[i].state];
449             break;
450             case WINED3DFUNC_NOTSUPPORTED: /* nop */
451                 TRACE("(%p) : %s function is not supported by this opengl implementation\n", This, "unknown" /* TODO: replace with debug_blah... */);
452                 *state = samplerStates[textureObjectSamplerStates[i].state];
453             break;
454             }
455         }
456         state++;
457     }
458
459     for(i = 0 ;textureObjectTextureStates[i].state != - 1; i++) {
460         if(*state != textureStates[textureObjectTextureStates[i].state] ) {
461             /* apply the state */
462             *state = textureStates[textureObjectTextureStates[i].state];
463             switch (textureObjectTextureStates[i].function) {
464             case WINED3DTSS_ADDRESSW:
465             /* I'm not sure what to do if this is set as well as ADDRESSW on the sampler, how do they interact together? */
466             break;
467             case WINED3DFUNC_UNIMPLEMENTED: /* unimplemented */
468             TRACE("(%p) : stub\n", This);
469             break;
470             case WINED3DFUNC_NOTSUPPORTED: /* nop */
471             TRACE("(%p) : function no supported by this opengl implementation\n", This);
472             break;
473             }
474         }
475         state++;
476     }
477 }
478
479
480 static const IWineD3DBaseTextureVtbl IWineD3DBaseTexture_Vtbl =
481 {
482     /* IUnknown */
483     IWineD3DBaseTextureImpl_QueryInterface,
484     IWineD3DBaseTextureImpl_AddRef,
485     IWineD3DBaseTextureImpl_Release,
486     /* IWineD3DResource */
487     IWineD3DBaseTextureImpl_GetParent,
488     IWineD3DBaseTextureImpl_GetDevice,
489     IWineD3DBaseTextureImpl_SetPrivateData,
490     IWineD3DBaseTextureImpl_GetPrivateData,
491     IWineD3DBaseTextureImpl_FreePrivateData,
492     IWineD3DBaseTextureImpl_SetPriority,
493     IWineD3DBaseTextureImpl_GetPriority,
494     IWineD3DBaseTextureImpl_PreLoad,
495     IWineD3DBaseTextureImpl_GetType,
496     /*IWineD3DBaseTexture*/
497     IWineD3DBaseTextureImpl_SetLOD,
498     IWineD3DBaseTextureImpl_GetLOD,
499     IWineD3DBaseTextureImpl_GetLevelCount,
500     IWineD3DBaseTextureImpl_SetAutoGenFilterType,
501     IWineD3DBaseTextureImpl_GetAutoGenFilterType,
502     IWineD3DBaseTextureImpl_GenerateMipSubLevels,
503     IWineD3DBaseTextureImpl_SetDirty,
504     IWineD3DBaseTextureImpl_GetDirty,
505     /* internal */
506     IWineD3DBaseTextureImpl_BindTexture,
507     IWineD3DBaseTextureImpl_UnBindTexture,
508     IWineD3DBaseTextureImpl_GetTextureDimensions,
509     IWineD3DBaseTextureImpl_ApplyStateChanges
510
511 };