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