wined3d: Some render target->texture blit context handling.
[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         ENTER_GL();
104         ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
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                 This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = samplerStates[WINED3DSAMP_MIPFILTER];
407             case WINED3DSAMP_MIPFILTER: /* fall through */
408                 {
409                     GLint glValue;
410                     *state = samplerStates[textureObjectSamplerStates[i].state];
411                     if (This->baseTexture.states[WINED3DTEXSTA_MINFILTER] < WINED3DTEXF_NONE ||
412                         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] < WINED3DTEXF_NONE ||
413                         This->baseTexture.states[WINED3DTEXSTA_MINFILTER] > WINED3DTEXF_ANISOTROPIC ||
414                         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] > WINED3DTEXF_LINEAR)
415                     {
416
417                         FIXME("Unrecognized or unsupported D3DSAMP_MINFILTER value %d, state %d D3DSAMP_MIPFILTER value %d, state %d\n",
418                                 This->baseTexture.states[WINED3DTEXSTA_MINFILTER],
419                                 textureObjectSamplerStates[WINED3DTEXSTA_MINFILTER].function,
420                                 This->baseTexture.states[WINED3DTEXSTA_MIPFILTER],
421                                 textureObjectSamplerStates[WINED3DTEXSTA_MIPFILTER].function);
422                     }
423                     glValue = minMipLookup[min(max(This->baseTexture.states[WINED3DTEXSTA_MINFILTER],WINED3DTEXF_NONE), WINED3DTEXF_ANISOTROPIC)]
424                                                 [min(max(This->baseTexture.states[WINED3DTEXSTA_MIPFILTER],WINED3DTEXF_NONE), WINED3DTEXF_LINEAR)];
425
426                     TRACE("ValueMIN=%d, ValueMIP=%d, setting MINFILTER to %x\n", 
427                             This->baseTexture.states[WINED3DTEXSTA_MINFILTER], 
428                             This->baseTexture.states[WINED3DTEXSTA_MIPFILTER], glValue);
429                     glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, glValue);
430                     checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
431                 }
432             break;
433             case WINED3DSAMP_MAXMIPLEVEL:
434                 *state = samplerStates[textureObjectSamplerStates[i].state];
435                 /**
436                 * Not really the same, but the more apprioprate than nothing
437                 */
438                 glTexParameteri(textureDimensions, GL_TEXTURE_BASE_LEVEL, *state);
439             break;
440             case WINED3DSAMP_MAXANISOTROPY:
441                 *state = samplerStates[textureObjectSamplerStates[i].state];
442                 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
443                     glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT,  *state);
444                     checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
445                 } else {
446                     WARN("Unsupported in local OpenGL implementation: glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT\n");
447                 }
448             break;
449             case WINED3DFUNC_UNIMPLEMENTED: /* unimplemented */
450                 TRACE("(%p) : stub\n", This);
451                 *state = samplerStates[textureObjectSamplerStates[i].state];
452             break;
453             case WINED3DFUNC_NOTSUPPORTED: /* nop */
454                 TRACE("(%p) : %s function is not supported by this opengl implementation\n", This, "unknown" /* TODO: replace with debug_blah... */);
455                 *state = samplerStates[textureObjectSamplerStates[i].state];
456             break;
457             }
458         }
459         state++;
460     }
461 }
462
463
464 static const IWineD3DBaseTextureVtbl IWineD3DBaseTexture_Vtbl =
465 {
466     /* IUnknown */
467     IWineD3DBaseTextureImpl_QueryInterface,
468     IWineD3DBaseTextureImpl_AddRef,
469     IWineD3DBaseTextureImpl_Release,
470     /* IWineD3DResource */
471     IWineD3DBaseTextureImpl_GetParent,
472     IWineD3DBaseTextureImpl_GetDevice,
473     IWineD3DBaseTextureImpl_SetPrivateData,
474     IWineD3DBaseTextureImpl_GetPrivateData,
475     IWineD3DBaseTextureImpl_FreePrivateData,
476     IWineD3DBaseTextureImpl_SetPriority,
477     IWineD3DBaseTextureImpl_GetPriority,
478     IWineD3DBaseTextureImpl_PreLoad,
479     IWineD3DBaseTextureImpl_GetType,
480     /*IWineD3DBaseTexture*/
481     IWineD3DBaseTextureImpl_SetLOD,
482     IWineD3DBaseTextureImpl_GetLOD,
483     IWineD3DBaseTextureImpl_GetLevelCount,
484     IWineD3DBaseTextureImpl_SetAutoGenFilterType,
485     IWineD3DBaseTextureImpl_GetAutoGenFilterType,
486     IWineD3DBaseTextureImpl_GenerateMipSubLevels,
487     IWineD3DBaseTextureImpl_SetDirty,
488     IWineD3DBaseTextureImpl_GetDirty,
489     /* internal */
490     IWineD3DBaseTextureImpl_BindTexture,
491     IWineD3DBaseTextureImpl_UnBindTexture,
492     IWineD3DBaseTextureImpl_GetTextureDimensions,
493     IWineD3DBaseTextureImpl_ApplyStateChanges
494
495 };