wininet: Default to keep-alive when the server is HTTP/1.1, not when it isn't.
[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  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25 #include "wined3d_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
28 #define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
29
30 /* *******************************************
31    IWineD3DBaseTexture IUnknown parts follow
32    ******************************************* */
33 HRESULT WINAPI IWineD3DBaseTextureImpl_QueryInterface(IWineD3DBaseTexture *iface, REFIID riid, LPVOID *ppobj)
34 {
35     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
36     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
37     if (IsEqualGUID(riid, &IID_IUnknown)
38         || IsEqualGUID(riid, &IID_IWineD3DBase)
39         || IsEqualGUID(riid, &IID_IWineD3DResource)
40         || IsEqualGUID(riid, &IID_IWineD3DBaseTexture)) {
41         IUnknown_AddRef(iface);
42         *ppobj = This;
43         return S_OK;
44     }
45     *ppobj = NULL;
46     return E_NOINTERFACE;
47 }
48
49 ULONG WINAPI IWineD3DBaseTextureImpl_AddRef(IWineD3DBaseTexture *iface) {
50     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
51     ULONG ref = InterlockedIncrement(&This->resource.ref);
52
53     TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1);
54     return ref;
55 }
56
57 ULONG WINAPI IWineD3DBaseTextureImpl_Release(IWineD3DBaseTexture *iface) {
58     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
59     ULONG ref = InterlockedDecrement(&This->resource.ref);
60     TRACE("(%p) : Releasing from %d\n", This, ref + 1);
61     if (ref == 0) {
62         IWineD3DBaseTextureImpl_CleanUp(iface);
63         HeapFree(GetProcessHeap(), 0, This);
64     }
65     return ref;
66 }
67
68 /* class static */
69 void IWineD3DBaseTextureImpl_CleanUp(IWineD3DBaseTexture *iface) {
70     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
71     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
72
73     TRACE("(%p) : textureName(%d)\n", This, This->baseTexture.textureName);
74     if (This->baseTexture.textureName != 0) {
75         ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
76         ENTER_GL();
77         TRACE("(%p) : Deleting texture %d\n", This, This->baseTexture.textureName);
78         glDeleteTextures(1, &This->baseTexture.textureName);
79         LEAVE_GL();
80     }
81     IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
82 }
83
84 /* ****************************************************
85    IWineD3DBaseTexture IWineD3DResource parts follow
86    **************************************************** */
87 HRESULT WINAPI IWineD3DBaseTextureImpl_GetDevice(IWineD3DBaseTexture *iface, IWineD3DDevice** ppDevice) {
88     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
89 }
90
91 HRESULT WINAPI IWineD3DBaseTextureImpl_SetPrivateData(IWineD3DBaseTexture *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
92     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
93 }
94
95 HRESULT WINAPI IWineD3DBaseTextureImpl_GetPrivateData(IWineD3DBaseTexture *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
96     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
97 }
98
99 HRESULT WINAPI IWineD3DBaseTextureImpl_FreePrivateData(IWineD3DBaseTexture *iface, REFGUID refguid) {
100     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
101 }
102
103 DWORD    WINAPI        IWineD3DBaseTextureImpl_SetPriority(IWineD3DBaseTexture *iface, DWORD PriorityNew) {
104     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
105 }
106
107 DWORD    WINAPI        IWineD3DBaseTextureImpl_GetPriority(IWineD3DBaseTexture *iface) {
108     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
109 }
110
111 void     WINAPI        IWineD3DBaseTextureImpl_PreLoad(IWineD3DBaseTexture *iface) {
112     IWineD3DResourceImpl_PreLoad((IWineD3DResource *)iface);
113 }
114
115 void     WINAPI        IWineD3DBaseTextureImpl_UnLoad(IWineD3DBaseTexture *iface) {
116     IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
117     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
118
119     if(This->baseTexture.textureName) {
120         ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
121         ENTER_GL();
122         glDeleteTextures(1, &This->baseTexture.textureName);
123         This->baseTexture.textureName = 0;
124         LEAVE_GL();
125     }
126     This->baseTexture.dirty = TRUE;
127 }
128
129 WINED3DRESOURCETYPE WINAPI IWineD3DBaseTextureImpl_GetType(IWineD3DBaseTexture *iface) {
130     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
131 }
132
133 HRESULT WINAPI IWineD3DBaseTextureImpl_GetParent(IWineD3DBaseTexture *iface, IUnknown **pParent) {
134     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
135 }
136
137 /* ******************************************************
138    IWineD3DBaseTexture IWineD3DBaseTexture parts follow
139    ****************************************************** */
140
141 /* There is no OpenGL equivalent of setLOD, getLOD. All they do anyway is prioritize texture loading
142  * so just pretend that they work unless something really needs a failure. */
143 DWORD WINAPI IWineD3DBaseTextureImpl_SetLOD(IWineD3DBaseTexture *iface, DWORD LODNew) {
144     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
145
146     if (This->resource.pool != WINED3DPOOL_MANAGED) {
147         return  WINED3DERR_INVALIDCALL;
148     }
149
150     if(LODNew >= This->baseTexture.levels)
151         LODNew = This->baseTexture.levels - 1;
152      This->baseTexture.LOD = LODNew;
153
154     TRACE("(%p) : set bogus LOD to %d\n", This, This->baseTexture.LOD);
155
156     return This->baseTexture.LOD;
157 }
158
159 DWORD WINAPI IWineD3DBaseTextureImpl_GetLOD(IWineD3DBaseTexture *iface) {
160     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
161
162     if (This->resource.pool != WINED3DPOOL_MANAGED) {
163         return  WINED3DERR_INVALIDCALL;
164     }
165
166     TRACE("(%p) : returning %d\n", This, This->baseTexture.LOD);
167
168     return This->baseTexture.LOD;
169 }
170
171 DWORD WINAPI IWineD3DBaseTextureImpl_GetLevelCount(IWineD3DBaseTexture *iface) {
172     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
173     TRACE("(%p) : returning %d\n", This, This->baseTexture.levels);
174     return This->baseTexture.levels;
175 }
176
177 HRESULT WINAPI IWineD3DBaseTextureImpl_SetAutoGenFilterType(IWineD3DBaseTexture *iface, WINED3DTEXTUREFILTERTYPE FilterType) {
178   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
179   IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
180   UINT textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
181
182   if (!(This->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)) {
183       TRACE("(%p) : returning invalid call\n", This);
184       return WINED3DERR_INVALIDCALL;
185   }
186   if(This->baseTexture.filterType != FilterType) {
187       /* What about multithreading? Do we want all the context overhead just to set this value?
188        * Or should we delay the applying until the texture is used for drawing? For now, apply
189        * immediately.
190        */
191       ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
192       ENTER_GL();
193       glBindTexture(textureDimensions, This->baseTexture.textureName);
194       checkGLcall("glBindTexture");
195       switch(FilterType) {
196           case WINED3DTEXF_NONE:
197           case WINED3DTEXF_POINT:
198               glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST);
199               checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST)");
200
201               break;
202           case WINED3DTEXF_LINEAR:
203               glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
204               checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST)");
205
206               break;
207           default:
208               WARN("Unexpected filter type %d, setting to GL_NICEST\n", FilterType);
209               glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
210               checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST)");
211       }
212       LEAVE_GL();
213   }
214   This->baseTexture.filterType = FilterType;
215   TRACE("(%p) :\n", This);
216   return WINED3D_OK;
217 }
218
219 WINED3DTEXTUREFILTERTYPE WINAPI IWineD3DBaseTextureImpl_GetAutoGenFilterType(IWineD3DBaseTexture *iface) {
220   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
221   FIXME("(%p) : stub\n", This);
222   if (!(This->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)) {
223      return WINED3DTEXF_NONE;
224   }
225   return This->baseTexture.filterType;
226 }
227
228 void WINAPI IWineD3DBaseTextureImpl_GenerateMipSubLevels(IWineD3DBaseTexture *iface) {
229   IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
230   /* TODO: implement filters using GL_SGI_generate_mipmaps http://oss.sgi.com/projects/ogl-sample/registry/SGIS/generate_mipmap.txt */
231   FIXME("(%p) : stub\n", This);
232   return ;
233 }
234
235 /* Internal function, No d3d mapping */
236 BOOL WINAPI IWineD3DBaseTextureImpl_SetDirty(IWineD3DBaseTexture *iface, BOOL dirty) {
237     BOOL old;
238     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
239     old = This->baseTexture.dirty;
240     This->baseTexture.dirty = dirty;
241     return old;
242 }
243
244 BOOL WINAPI IWineD3DBaseTextureImpl_GetDirty(IWineD3DBaseTexture *iface) {
245     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
246     return This->baseTexture.dirty;
247 }
248
249 HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) {
250     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
251     HRESULT hr = WINED3D_OK;
252     UINT textureDimensions;
253     BOOL isNewTexture = FALSE;
254     TRACE("(%p) : About to bind texture\n", This);
255
256     textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
257     ENTER_GL();
258     /* Generate a texture name if we don't already have one */
259     if (This->baseTexture.textureName == 0) {
260         glGenTextures(1, &This->baseTexture.textureName);
261         checkGLcall("glGenTextures");
262         TRACE("Generated texture %d\n", This->baseTexture.textureName);
263         if (This->resource.pool == WINED3DPOOL_DEFAULT) {
264             /* Tell opengl to try and keep this texture in video ram (well mostly) */
265             GLclampf tmp;
266             tmp = 0.9f;
267             glPrioritizeTextures(1, &This->baseTexture.textureName, &tmp);
268
269         }
270         /* Initialise the state of the texture object
271         to the openGL defaults, not the directx defaults */
272         This->baseTexture.states[WINED3DTEXSTA_ADDRESSU]      = WINED3DTADDRESS_WRAP;
273         This->baseTexture.states[WINED3DTEXSTA_ADDRESSV]      = WINED3DTADDRESS_WRAP;
274         This->baseTexture.states[WINED3DTEXSTA_ADDRESSW]      = WINED3DTADDRESS_WRAP;
275         This->baseTexture.states[WINED3DTEXSTA_BORDERCOLOR]   = 0;
276         This->baseTexture.states[WINED3DTEXSTA_MAGFILTER]     = WINED3DTEXF_LINEAR;
277         This->baseTexture.states[WINED3DTEXSTA_MINFILTER]     = WINED3DTEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
278         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER]     = WINED3DTEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
279         This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL]   = 0;
280         This->baseTexture.states[WINED3DTEXSTA_MAXANISOTROPY] = 0;
281         This->baseTexture.states[WINED3DTEXSTA_SRGBTEXTURE]   = 0;
282         This->baseTexture.states[WINED3DTEXSTA_ELEMENTINDEX]  = 0;
283         This->baseTexture.states[WINED3DTEXSTA_DMAPOFFSET]    = 0;
284         This->baseTexture.states[WINED3DTEXSTA_TSSADDRESSW]   = WINED3DTADDRESS_WRAP;
285         IWineD3DBaseTexture_SetDirty(iface, TRUE);
286         isNewTexture = TRUE;
287
288         if(This->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP) {
289             /* This means double binding the texture at creation, but keeps the code simpler all
290              * in all, and the run-time path free from additional checks
291              */
292             glBindTexture(textureDimensions, This->baseTexture.textureName);
293             checkGLcall("glBindTexture");
294             glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
295             checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_SGIS, GL_TRUE)");
296         }
297     }
298
299     /* Bind the texture */
300     if (This->baseTexture.textureName != 0) {
301         glBindTexture(textureDimensions, This->baseTexture.textureName);
302         checkGLcall("glBindTexture");
303         if (isNewTexture) {
304             /* For a new texture we have to set the textures levels after binding the texture.
305              * In theory this is all we should ever have to do, but because ATI's drivers are broken, we
306              * also need to set the texture dimensions before the texture is set
307              * Beware that texture rectangles do not support mipmapping, but set the maxmiplevel if we're
308              * relying on the partial GL_ARB_texture_non_power_of_two emulation with texture rectangles
309              * (ie, do not care for cond_np2 here, just look for GL_TEXTURE_RECTANGLE_ARB)
310              */
311             if(textureDimensions != GL_TEXTURE_RECTANGLE_ARB) {
312                 TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", This->baseTexture.levels - 1);
313                 glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels - 1);
314                 checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels)");
315             }
316             if(textureDimensions==GL_TEXTURE_CUBE_MAP_ARB) {
317                 /* Cubemaps are always set to clamp, regardless of the sampler state. */
318                 glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
319                 glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
320                 glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
321             }
322         }
323                 
324     } else { /* this only happened if we've run out of openGL textures */
325         WARN("This texture doesn't have an openGL texture assigned to it\n");
326         hr =  WINED3DERR_INVALIDCALL;
327     }
328
329     LEAVE_GL();
330     return hr;
331 }
332
333 HRESULT WINAPI IWineD3DBaseTextureImpl_UnBindTexture(IWineD3DBaseTexture *iface) {
334     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
335     UINT textureDimensions;
336
337     TRACE("(%p) : About to bind texture\n", This);
338     textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
339
340     ENTER_GL();
341
342     glBindTexture(textureDimensions, 0);
343 #if 0 /* TODO: context manager support */
344      IWineD3DContextManager_PopState(This->contextManager, textureDimensions, ENABLED, NOW /* make sure the state is applied now */);
345 #else
346     glDisable(textureDimensions);
347 #endif
348
349     LEAVE_GL();
350     return WINED3D_OK;
351 }
352
353 UINT WINAPI IWineD3DBaseTextureImpl_GetTextureDimensions(IWineD3DBaseTexture *iface){
354     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
355     FIXME("(%p) : This shouldn't be called\n", This);
356     return WINED3D_OK;
357 }
358
359 BOOL WINAPI IWineD3DBaseTextureImpl_IsCondNP2(IWineD3DBaseTexture *iface){
360     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
361     FIXME("(%p) : This shouldn't be called\n", This);
362     return FALSE;
363 }
364
365 static inline GLenum warpLookupType(WINED3DSAMPLERSTATETYPE Type) {
366     switch(Type) {
367     case WINED3DSAMP_ADDRESSU:
368         return GL_TEXTURE_WRAP_S;
369     case WINED3DSAMP_ADDRESSV:
370         return GL_TEXTURE_WRAP_T;
371     case WINED3DSAMP_ADDRESSW:
372         return GL_TEXTURE_WRAP_R;
373     default:
374         FIXME("Unexpected warp type %d\n", Type);
375         return 0;
376     }
377 }
378
379 static inline void apply_wrap(const GLint textureDimensions, const DWORD state, const GLint type,
380                               BOOL cond_np2) {
381     GLint wrapParm;
382
383     if (state < minLookup[WINELOOKUP_WARPPARAM] || state > maxLookup[WINELOOKUP_WARPPARAM]) {
384         FIXME("Unrecognized or unsupported WINED3DTADDRESS_U value %d\n", state);
385     } else {
386         if(textureDimensions==GL_TEXTURE_CUBE_MAP_ARB) {
387             /* Cubemaps are always set to clamp, regardless of the sampler state. */
388             wrapParm = GL_CLAMP_TO_EDGE;
389         } else if(cond_np2) {
390             if(state == WINED3DTADDRESS_WRAP) {
391                 wrapParm = GL_CLAMP_TO_EDGE;
392             } else {
393                 wrapParm = stateLookup[WINELOOKUP_WARPPARAM][state - minLookup[WINELOOKUP_WARPPARAM]];
394             }
395         } else {
396             wrapParm = stateLookup[WINELOOKUP_WARPPARAM][state - minLookup[WINELOOKUP_WARPPARAM]];
397         }
398         TRACE("Setting WRAP_S to %d for %x\n", wrapParm, textureDimensions);
399         glTexParameteri(textureDimensions, type, wrapParm);
400         checkGLcall("glTexParameteri(..., type, wrapParm)");
401     }
402 }
403
404 void WINAPI IWineD3DBaseTextureImpl_ApplyStateChanges(IWineD3DBaseTexture *iface,
405                                     const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1],
406                                     const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) {
407     IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
408     DWORD state;
409     GLint textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
410     BOOL cond_np2 = IWineD3DBaseTexture_IsCondNP2(iface);
411
412     IWineD3DBaseTexture_PreLoad(iface);
413
414     if(samplerStates[WINED3DSAMP_ADDRESSU]      != This->baseTexture.states[WINED3DTEXSTA_ADDRESSU]) {
415         state = samplerStates[WINED3DSAMP_ADDRESSU];
416         apply_wrap(textureDimensions, state, GL_TEXTURE_WRAP_S, cond_np2);
417         This->baseTexture.states[WINED3DTEXSTA_ADDRESSU] = state;
418     }
419
420     if(samplerStates[WINED3DSAMP_ADDRESSV]      != This->baseTexture.states[WINED3DTEXSTA_ADDRESSV]) {
421         state = samplerStates[WINED3DSAMP_ADDRESSV];
422         apply_wrap(textureDimensions, state, GL_TEXTURE_WRAP_T, cond_np2);
423         This->baseTexture.states[WINED3DTEXSTA_ADDRESSV] = state;
424     }
425
426     if(samplerStates[WINED3DSAMP_ADDRESSW]      != This->baseTexture.states[WINED3DTEXSTA_ADDRESSW]) {
427         state = samplerStates[WINED3DSAMP_ADDRESSW];
428         apply_wrap(textureDimensions, state, GL_TEXTURE_WRAP_R, cond_np2);
429         This->baseTexture.states[WINED3DTEXSTA_ADDRESSW] = state;
430     }
431
432     if(samplerStates[WINED3DSAMP_BORDERCOLOR]   != This->baseTexture.states[WINED3DTEXSTA_BORDERCOLOR]) {
433         float col[4];
434
435         state = samplerStates[WINED3DSAMP_BORDERCOLOR];
436         D3DCOLORTOGLFLOAT4(state, col);
437         TRACE("Setting border color for %u to %x\n", textureDimensions, state);
438         glTexParameterfv(textureDimensions, GL_TEXTURE_BORDER_COLOR, &col[0]);
439         checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
440         This->baseTexture.states[WINED3DTEXSTA_BORDERCOLOR] = state;
441     }
442
443     if(samplerStates[WINED3DSAMP_MAGFILTER]     != This->baseTexture.states[WINED3DTEXSTA_MAGFILTER]) {
444         GLint glValue;
445         state = samplerStates[WINED3DSAMP_MAGFILTER];
446         if (state > WINED3DTEXF_ANISOTROPIC) {
447             FIXME("Unrecognized or unsupported MAGFILTER* value %d\n", state);
448         } else {
449             glValue = (*This->baseTexture.magLookup)[state - WINED3DTEXF_NONE];
450             TRACE("ValueMAG=%d setting MAGFILTER to %x\n", state, glValue);
451             glTexParameteri(textureDimensions, GL_TEXTURE_MAG_FILTER, glValue);
452             /* We need to reset the Anisotropic filtering state when we change the mag filter to WINED3DTEXF_ANISOTROPIC (this seems a bit weird, check the documentation to see how it should be switched off. */
453             if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && WINED3DTEXF_ANISOTROPIC == state &&
454                 !cond_np2) {
455                 glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, samplerStates[WINED3DSAMP_MAXANISOTROPY]);
456             }
457             This->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = state;
458         }
459     }
460
461     if((samplerStates[WINED3DSAMP_MINFILTER]     != This->baseTexture.states[WINED3DTEXSTA_MINFILTER] ||
462         samplerStates[WINED3DSAMP_MIPFILTER]     != This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] ||
463         samplerStates[WINED3DSAMP_MAXMIPLEVEL]   != This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL])) {
464         GLint glValue;
465
466         This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = samplerStates[WINED3DSAMP_MIPFILTER];
467         This->baseTexture.states[WINED3DTEXSTA_MINFILTER] = samplerStates[WINED3DSAMP_MINFILTER];
468         This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL] = samplerStates[WINED3DSAMP_MAXMIPLEVEL];
469
470         if (This->baseTexture.states[WINED3DTEXSTA_MINFILTER] > WINED3DTEXF_ANISOTROPIC ||
471             This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] > WINED3DTEXF_LINEAR)
472         {
473
474             FIXME("Unrecognized or unsupported D3DSAMP_MINFILTER value %d D3DSAMP_MIPFILTER value %d\n",
475                   This->baseTexture.states[WINED3DTEXSTA_MINFILTER],
476                   This->baseTexture.states[WINED3DTEXSTA_MIPFILTER]);
477         }
478         glValue = (*This->baseTexture.minMipLookup)
479                 [min(max(samplerStates[WINED3DSAMP_MINFILTER],WINED3DTEXF_NONE), WINED3DTEXF_ANISOTROPIC)]
480                 [min(max(samplerStates[WINED3DSAMP_MIPFILTER],WINED3DTEXF_NONE), WINED3DTEXF_LINEAR)];
481
482         TRACE("ValueMIN=%d, ValueMIP=%d, setting MINFILTER to %x\n",
483               samplerStates[WINED3DSAMP_MINFILTER],
484               samplerStates[WINED3DSAMP_MIPFILTER], glValue);
485         glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, glValue);
486         checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
487
488         if(!cond_np2) {
489             if(This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] == WINED3DTEXF_NONE) {
490                 glValue = 0;
491             } else if(This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL] >= This->baseTexture.levels) {
492                 glValue = This->baseTexture.levels - 1;
493             } else {
494                 glValue = This->baseTexture.states[WINED3DTEXSTA_MAXMIPLEVEL];
495             }
496             glTexParameteri(textureDimensions, GL_TEXTURE_BASE_LEVEL, glValue);
497         }
498     }
499
500     if(samplerStates[WINED3DSAMP_MAXANISOTROPY] != This->baseTexture.states[WINED3DTEXSTA_MAXANISOTROPY]) {
501         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && !cond_np2) {
502             glTexParameteri(textureDimensions, GL_TEXTURE_MAX_ANISOTROPY_EXT, samplerStates[WINED3DSAMP_MAXANISOTROPY]);
503             checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
504         } else {
505             WARN("Unsupported in local OpenGL implementation: glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT\n");
506         }
507         This->baseTexture.states[WINED3DTEXSTA_MAXANISOTROPY] = samplerStates[WINED3DSAMP_MAXANISOTROPY];
508     }
509 }
510
511
512 static const IWineD3DBaseTextureVtbl IWineD3DBaseTexture_Vtbl =
513 {
514     /* IUnknown */
515     IWineD3DBaseTextureImpl_QueryInterface,
516     IWineD3DBaseTextureImpl_AddRef,
517     IWineD3DBaseTextureImpl_Release,
518     /* IWineD3DResource */
519     IWineD3DBaseTextureImpl_GetParent,
520     IWineD3DBaseTextureImpl_GetDevice,
521     IWineD3DBaseTextureImpl_SetPrivateData,
522     IWineD3DBaseTextureImpl_GetPrivateData,
523     IWineD3DBaseTextureImpl_FreePrivateData,
524     IWineD3DBaseTextureImpl_SetPriority,
525     IWineD3DBaseTextureImpl_GetPriority,
526     IWineD3DBaseTextureImpl_PreLoad,
527     IWineD3DBaseTextureImpl_UnLoad,
528     IWineD3DBaseTextureImpl_GetType,
529     /*IWineD3DBaseTexture*/
530     IWineD3DBaseTextureImpl_SetLOD,
531     IWineD3DBaseTextureImpl_GetLOD,
532     IWineD3DBaseTextureImpl_GetLevelCount,
533     IWineD3DBaseTextureImpl_SetAutoGenFilterType,
534     IWineD3DBaseTextureImpl_GetAutoGenFilterType,
535     IWineD3DBaseTextureImpl_GenerateMipSubLevels,
536     IWineD3DBaseTextureImpl_SetDirty,
537     IWineD3DBaseTextureImpl_GetDirty,
538     /* internal */
539     IWineD3DBaseTextureImpl_BindTexture,
540     IWineD3DBaseTextureImpl_UnBindTexture,
541     IWineD3DBaseTextureImpl_GetTextureDimensions,
542     IWineD3DBaseTextureImpl_IsCondNP2,
543     IWineD3DBaseTextureImpl_ApplyStateChanges
544
545 };