crypt32: Fixed day/month mismatch in time encoding routines.
[wine] / dlls / wined3d / device.c
1 /*
2  * IWineD3DDevice implementation
3  *
4  * Copyright 2002-2005 Jason Edmeades
5  * Copyright 2003-2004 Raphael Junqueira
6  * Copyright 2004 Christian Costa
7  * Copyright 2005 Oliver Stieber
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include "config.h"
25 #ifdef HAVE_FLOAT_H
26 # include <float.h>
27 #endif
28 #include "wined3d_private.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
32
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
36 {
37     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
38     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
39     X11DRV_GET_FONT,      /* get current X font for a DC */
40 };
41
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
44 {
45     Display *display;
46     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
47
48     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49                     sizeof(display), (LPSTR)&display )) display = NULL;
50     return display;
51 }
52
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
55
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support     = FALSE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
61
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
64
65 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
66
67 /* helper macros */
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
69
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72     D3DMEMCHECK(object, pp##type); \
73     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
74     object->wineD3DDevice = This; \
75     object->parent       = parent; \
76     object->ref          = 1; \
77     *pp##type = (IWineD3D##type *) object; \
78 }
79
80 #define  D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82     D3DMEMCHECK(object, pp##type); \
83     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
84     object->resource.wineD3DDevice   = This; \
85     object->resource.parent          = parent; \
86     object->resource.resourceType    = d3dtype; \
87     object->resource.ref             = 1; \
88     object->resource.pool            = Pool; \
89     object->resource.format          = Format; \
90     object->resource.usage           = Usage; \
91     object->resource.size            = _size; \
92     /* Check that we have enough video ram left */ \
93     if (Pool == WINED3DPOOL_DEFAULT) { \
94         if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95             WARN("Out of 'bogus' video memory\n"); \
96             HeapFree(GetProcessHeap(), 0, object); \
97             *pp##type = NULL; \
98             return WINED3DERR_OUTOFVIDEOMEMORY; \
99         } \
100         globalChangeGlRam(_size); \
101     } \
102     object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103     if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
104         FIXME("Out of memory!\n"); \
105         HeapFree(GetProcessHeap(), 0, object); \
106         *pp##type = NULL; \
107         return WINED3DERR_OUTOFVIDEOMEMORY; \
108     } \
109     *pp##type = (IWineD3D##type *) object; \
110     IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111     TRACE("(%p) : Created resource %p\n", This, object); \
112 }
113
114 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
115     _basetexture.levels     = Levels; \
116     _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
117     _basetexture.LOD        = 0; \
118     _basetexture.dirty      = TRUE; \
119 }
120
121 /**********************************************************
122  * Global variable / Constants follow
123  **********************************************************/
124 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
125
126 /**********************************************************
127  * Utility functions follow
128  **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
131
132     float quad_att;
133     float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
134     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
135
136     /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137     glMatrixMode(GL_MODELVIEW);
138     glPushMatrix();
139     glLoadMatrixf((float *)&This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
140
141     /* Diffuse: */
142     colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
143     colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
144     colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
145     colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
146     glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
147     checkGLcall("glLightfv");
148
149     /* Specular */
150     colRGBA[0] = lightInfo->OriginalParms.Specular.r;
151     colRGBA[1] = lightInfo->OriginalParms.Specular.g;
152     colRGBA[2] = lightInfo->OriginalParms.Specular.b;
153     colRGBA[3] = lightInfo->OriginalParms.Specular.a;
154     glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
155     checkGLcall("glLightfv");
156
157     /* Ambient */
158     colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
159     colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
160     colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
161     colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
162     glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
163     checkGLcall("glLightfv");
164
165     /* Attenuation - Are these right? guessing... */
166     glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
167     checkGLcall("glLightf");
168     glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
169     checkGLcall("glLightf");
170
171     if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
172         quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
173     } else {
174         quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
175     }
176
177     if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
178     glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
179     checkGLcall("glLightf");
180
181     switch (lightInfo->OriginalParms.Type) {
182     case D3DLIGHT_POINT:
183         /* Position */
184         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
185         checkGLcall("glLightfv");
186         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
187         checkGLcall("glLightf");
188         /* FIXME: Range */
189         break;
190
191     case D3DLIGHT_SPOT:
192         /* Position */
193         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
194         checkGLcall("glLightfv");
195         /* Direction */
196         glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
197         checkGLcall("glLightfv");
198         glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
199         checkGLcall("glLightf");
200         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
201         checkGLcall("glLightf");
202         /* FIXME: Range */
203         break;
204
205     case D3DLIGHT_DIRECTIONAL:
206         /* Direction */
207         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
208         checkGLcall("glLightfv");
209         glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
210         checkGLcall("glLightf");
211         glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
212         checkGLcall("glLightf");
213         break;
214
215     default:
216         FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
217     }
218
219     /* Restore the modelview matrix */
220     glPopMatrix();
221 }
222
223 /* Apply the current values to the specified texture stage */
224 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
225     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
226     float col[4];
227
228     union {
229         float f;
230         DWORD d;
231     } tmpvalue;
232
233     /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234     clamping, MIPLOD, etc. This will work for up to 16 samplers.
235     */
236    
237     if (Sampler >= GL_LIMITS(samplers)) {
238         FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
239         return;
240     }
241     VTRACE(("Activating appropriate texture state %ld\n", Sampler));
242     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
243         ENTER_GL();
244         GLACTIVETEXTURE(Sampler);
245         LEAVE_GL();
246         /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247     } else if (Sampler > 0) {
248         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
249         return;
250     }
251
252     /* TODO: change this to a lookup table
253         LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254         LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255         etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256         especially when there are a number of groups of states. */
257
258     TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler);
259
260     /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list  */
261 #define APPLY_STATE(_state)     IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263     APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
264     APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
265 #if 0 /* not supported at the moment */
266     APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
267     APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
268     APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
269     APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
270     APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
271     APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
272     APPLY_STATE(WINED3DTSS_RESULTARG);
273     APPLY_STATE(WINED3DTSS_CONSTANT);
274 #endif
275     /* a quick sanity check in case someone forgot to update this function */
276     if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
277         FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
278     }
279 #undef APPLY_STATE
280
281     /* apply any sampler states that always need applying */
282     if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
283         tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
284         glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
285                 GL_TEXTURE_LOD_BIAS_EXT,
286                 tmpvalue.f);
287         checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
288     }
289
290     /* Note the D3DRS value applies to all textures, but GL has one
291      *  per texture, so apply it now ready to be used!
292      */
293     D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294     /* Set the default alpha blend color */
295     glBlendColor(col[0], col[1], col[2], col[3]);
296     checkGLcall("glBlendColor");
297
298     D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
299     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
300     checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
301
302     /* TODO: NV_POINT_SPRITE */
303     if (GL_SUPPORT(ARB_POINT_SPRITE)) {
304         if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE] != FALSE) {
305            /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
306            glDisable(GL_POINT_SMOOTH);
307
308            /* Centre the texture on the vertex */
309            VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
310            glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
311
312            VTRACE("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n");
313            glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
314            checkGLcall("glTexEnvf(...)");
315            VTRACE("glEnable( GL_POINT_SPRITE_ARB )\n");
316            glEnable( GL_POINT_SPRITE_ARB );
317            checkGLcall("glEnable(...)");
318         } else {
319            VTRACE("glDisable( GL_POINT_SPRITE_ARB )\n");
320            glDisable( GL_POINT_SPRITE_ARB );
321            checkGLcall("glEnable(...)");
322         }
323     }
324
325     TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler);
326 }
327
328 /**********************************************************
329  * IUnknown parts follows
330  **********************************************************/
331
332 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
333 {
334     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
335
336     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
337     if (IsEqualGUID(riid, &IID_IUnknown)
338         || IsEqualGUID(riid, &IID_IWineD3DBase)
339         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
340         IUnknown_AddRef(iface);
341         *ppobj = This;
342         return WINED3D_OK;
343     }
344
345     return E_NOINTERFACE;
346 }
347
348 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
349     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
350     ULONG refCount = InterlockedIncrement(&This->ref);
351
352     TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
353     return refCount;
354 }
355
356 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
357     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
358     ULONG refCount = InterlockedDecrement(&This->ref);
359
360     TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
361
362     if (!refCount) {
363         /* TODO: Clean up all the surfaces and textures! */
364         /* FIXME: Create targets and state blocks in d3d8 */
365         if (((IWineD3DImpl *)This->wineD3D)->dxVersion >= 8) { /*We don't create state blocks for d3d7 yet*/
366             /* NOTE: You must release the parent if the object was created via a callback
367             ** ***************************/
368             /* TODO: this is exactly the same as required by _Reset.., so at some point we need to move the code so that is can be called by reset add release...  */
369             /* Release all of the swapchains, except the implicit swapchain */
370             IUnknown* stencilBufferParent;
371             IUnknown* swapChainParent;
372
373             /* NOTE: Don't release swapchain 0 here, it's 'special' */
374             SwapChainList *nextSwapchain = This->swapchains;
375             if (nextSwapchain != NULL) {
376                 nextSwapchain = nextSwapchain->next;
377             } else {
378                 WARN("Expected to find the implicit swapchain\n");
379             }
380
381             /* release all the other swapchains */
382             while (nextSwapchain != NULL) {
383                 SwapChainList *prevSwapchain = nextSwapchain;
384                 nextSwapchain = nextSwapchain->next;
385                 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
386                 /* NOTE: no need to free the list element, it will be done by the release callback
387                    HeapFree(GetProcessHeap(), 0, prevSwapchain); */
388             }
389              /* Release the buffers (with sanity checks)*/
390             if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
391                 if(This->depthStencilBuffer != This->stencilBufferTarget)
392                     FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
393             }
394             This->stencilBufferTarget = NULL;
395
396             if(IWineD3DSurface_Release(This->renderTarget) >0){
397                  /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
398             }
399             This->renderTarget = NULL;
400
401             IWineD3DSurface_GetParent(This->depthStencilBuffer, &stencilBufferParent);
402             IUnknown_Release(stencilBufferParent);          /* once for the get parent */
403             if(IUnknown_Release(stencilBufferParent)  >0){  /* the second time for when it was created */
404                 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
405             }
406             This->depthStencilBuffer = NULL;
407
408             /* Release the update stateblock */
409             if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
410                 if(This->updateStateBlock != This->stateBlock)
411                     FIXME("(%p) Something's still holding the Update stateblock\n",This);
412             }
413             This->updateStateBlock = NULL;
414             { /* because were not doing proper internal refcounts releasing the primary state block
415                 causes recursion with the extra checks in ResourceReleased, to avoid this we have
416                 to set this->stateBlock = NULL; first */
417                 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
418                 This->stateBlock = NULL;
419
420                 /* Release the stateblock */
421                 if(IWineD3DStateBlock_Release(stateBlock) > 0){
422                         FIXME("(%p) Something's still holding the Update stateblock\n",This);
423                 }
424             }
425
426             if (This->swapchains != NULL) {
427                 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
428                 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
429                 IUnknown_Release(swapChainParent);           /* once for the get parent */
430                 if (IUnknown_Release(swapChainParent)  > 0) {  /* the second time for when it was created */
431                     FIXME("(%p) Something's still holding the implicit swapchain\n", This);
432                 }
433             }
434
435             if (This->resources != NULL ) {
436                 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
437                 dumpResources(This->resources);
438             }
439
440         }
441         IWineD3D_Release(This->wineD3D);
442         This->wineD3D = NULL;
443         HeapFree(GetProcessHeap(), 0, This);
444         TRACE("Freed device  %p\n", This);
445         This = NULL;
446     }
447     return refCount;
448 }
449
450 /**********************************************************
451  * IWineD3DDevice implementation follows
452  **********************************************************/
453 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
454     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
455     *pParent = This->parent;
456     IUnknown_AddRef(This->parent);
457     return WINED3D_OK;
458 }
459
460 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, 
461                              DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
462                              IUnknown *parent) {
463     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
464     IWineD3DVertexBufferImpl *object;
465     WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
466     D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
467     
468     /*TODO: use VBO's */
469     if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
470         object->resource.allocatedMemory  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
471     }
472     object->fvf = FVF;
473
474     TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
475     *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
476
477     return WINED3D_OK;
478 }
479
480 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage, 
481                                                     WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
482                                                     HANDLE *sharedHandle, IUnknown *parent) {
483     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
484     IWineD3DIndexBufferImpl *object;
485     TRACE("(%p) Creating index buffer\n", This);
486     
487     /* Allocate the storage for the device */
488     D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
489     
490     /*TODO: use VBO's */
491     if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
492         object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
493     }
494
495     TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format, 
496                            debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
497     *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
498
499     return WINED3D_OK;
500 }
501
502 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
503
504     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
505     IWineD3DStateBlockImpl *object;
506     int i, j;
507
508     D3DCREATEOBJECTINSTANCE(object, StateBlock)
509     object->blockType     = Type;
510
511     /* Special case - Used during initialization to produce a placeholder stateblock
512           so other functions called can update a state block                         */
513     if (Type == WINED3DSBT_INIT) {
514         /* Don't bother increasing the reference count otherwise a device will never
515            be freed due to circular dependencies                                   */
516         return WINED3D_OK;
517     }
518
519     /* Otherwise, might as well set the whole state block to the appropriate values  */
520     if ( This->stateBlock != NULL) {
521        memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
522     } else {
523        memset(object->streamFreq, 1, sizeof(object->streamFreq));
524     }
525
526     /* Reset the ref and type after kludging it */
527     object->wineD3DDevice = This;
528     object->ref           = 1;
529     object->blockType     = Type;
530
531     TRACE("Updating changed flags appropriate for type %d\n", Type);
532
533     if (Type == WINED3DSBT_ALL) {
534
535         TRACE("ALL => Pretend everything has changed\n");
536         memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
537     } else if (Type == WINED3DSBT_PIXELSTATE) {
538
539         TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
540         memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
541
542         object->changed.pixelShader = TRUE;
543
544         /* Pixel Shader Constants */
545         for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
546             object->changed.pixelShaderConstants[i] = TRUE;
547         }
548         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
549             object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
550         }
551         for (j = 0; j < GL_LIMITS(textures); j++) {
552             for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
553                 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
554             }
555         }
556         for (j = 0 ; j < 16; j++) {
557             for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
558
559                 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
560             }
561         }
562
563     } else if (Type == WINED3DSBT_VERTEXSTATE) {
564
565         TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
566         memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
567
568         object->changed.vertexShader = TRUE;
569
570         /* Vertex Shader Constants */
571         for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
572             object->changed.vertexShaderConstants[i] = TRUE;
573         }
574         for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
575             object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
576         }
577         for (j = 0; j < GL_LIMITS(textures); j++) {
578             for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
579                 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
580             }
581         }
582         for (j = 0 ; j < 16; j++){
583             for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
584                 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
585             }
586         }
587
588     /* Duplicate light chain */
589     {
590         PLIGHTINFOEL *src = NULL;
591         PLIGHTINFOEL *dst = NULL;
592         PLIGHTINFOEL *newEl = NULL;
593         src = This->stateBlock->lights;
594         object->lights = NULL;
595
596
597         while (src) {
598             newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
599             if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
600             memcpy(newEl, src, sizeof(PLIGHTINFOEL));
601             newEl->prev = dst;
602             newEl->changed = TRUE;
603             newEl->enabledChanged = TRUE;
604             if (dst == NULL) {
605                 object->lights = newEl;
606             } else {
607                 dst->next = newEl;
608             }
609             dst = newEl;
610             src = src->next;
611         }
612
613      }
614
615     } else {
616         FIXME("Unrecognized state block type %d\n", Type);
617     }
618
619     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
620     return WINED3D_OK;
621 }
622
623
624 /* ************************************
625 MSDN:
626 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
627
628 Discard
629  [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. 
630
631 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
632
633 ******************************** */
634  
635 HRESULT  WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
636     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;    
637     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
638     unsigned int pow2Width, pow2Height;
639     unsigned int Size       = 1;
640     TRACE("(%p) Create surface\n",This);
641     
642     /** FIXME: Check ranges on the inputs are valid 
643      * MSDN
644      *   MultisampleQuality
645      *    [in] Quality level. The valid range is between zero and one less than the level
646      *    returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. 
647      *    Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
648      *    values of paired render targets, depth stencil surfaces, and the MultiSample type
649      *    must all match.
650       *******************************/
651
652
653     /**
654     * TODO: Discard MSDN
655     * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
656     *
657     * If this flag is set, the contents of the depth stencil buffer will be
658     * invalid after calling either IDirect3DDevice9::Present or  * IDirect3DDevice9::SetDepthStencilSurface
659     * with a different depth surface.
660     *
661     *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
662     ***************************/
663
664     if(MultisampleQuality < 0) {
665         FIXME("Invalid multisample level %ld\n", MultisampleQuality);
666         return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
667     }
668
669     if(MultisampleQuality > 0) {
670         FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality);
671         MultisampleQuality=0;
672     }
673
674     /** FIXME: Check that the format is supported
675     *    by the device.
676       *******************************/
677
678     /* Non-power2 support */
679
680     /* Find the nearest pow2 match */
681     pow2Width = pow2Height = 1;
682     while (pow2Width < Width) pow2Width <<= 1;
683     while (pow2Height < Height) pow2Height <<= 1;
684
685     if (pow2Width > Width || pow2Height > Height) {
686          /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
687         if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
688                || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
689             FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
690                     This, Width, Height);
691             return WINED3DERR_NOTAVAILABLE;
692         }
693     }
694
695     /** Check against the maximum texture sizes supported by the video card **/
696     if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
697         /* one of three options
698         1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
699         2: Set the texture to the maxium size (bad idea)
700         3:    WARN and return WINED3DERR_NOTAVAILABLE;
701         */
702         WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
703          return WINED3DERR_NOTAVAILABLE;
704     }
705
706
707
708     /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
709      *  it is based around 4x4 pixel blocks it requires padding, so allocate enough
710      *  space!
711       *********************************/
712     if (WINED3DFMT_UNKNOWN == Format) {
713         Size = 0;
714     } else if (Format == WINED3DFMT_DXT1) {
715         /* DXT1 is half byte per pixel */
716        Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
717
718     } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
719                Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
720        Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
721     } else {
722        Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
723     }
724
725     /** Create and initialise the surface resource **/
726     D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
727     /* "Standalone" surface */
728     IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
729
730     object->currentDesc.Width      = Width;
731     object->currentDesc.Height     = Height;
732     object->currentDesc.MultiSampleType    = MultiSample;
733     object->currentDesc.MultiSampleQuality = MultisampleQuality;
734
735     /* Setup some glformat defaults */
736     if (WINED3DFMT_UNKNOWN != Format) {
737         object->glDescription.glFormat         = D3DFmt2GLFmt(This, object->resource.format);
738         object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
739         object->glDescription.glType           = D3DFmt2GLType(This, object->resource.format);
740     } else {
741         object->glDescription.glFormat         = 0;
742         object->glDescription.glFormatInternal = 0;
743         object->glDescription.glType           = 0;
744     }
745
746     object->glDescription.textureName      = 0;
747     object->glDescription.level            = Level;
748     object->glDescription.target           = GL_TEXTURE_2D;
749
750     /* Internal data */
751     object->pow2Width  = pow2Width;
752     object->pow2Height = pow2Height;
753     object->nonpow2    = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
754     object->discard    = Discard;
755     object->activeLock = FALSE;
756
757     if (WINED3DFMT_UNKNOWN != Format) {
758         object->bytesPerPixel = D3DFmtGetBpp(This, Format);
759         object->pow2Size      = (pow2Width * object->bytesPerPixel) * pow2Height;
760     } else {
761         object->bytesPerPixel = 0;
762         object->pow2Size      = 0;
763     }
764
765     /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
766
767     TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
768
769     /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
770     * this function is too deap to need to care about things like this.
771     * Levels need to be checked too, and possibly Type wince they all affect what can be done.
772     * ****************************************/
773     switch(Pool) {
774     case WINED3DPOOL_SCRATCH:
775         if(Lockable == FALSE)
776             FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
777                 which are mutually exclusive, setting lockable to true\n");
778                 Lockable = TRUE;
779     break;
780     case WINED3DPOOL_SYSTEMMEM:
781         if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
782                                     this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
783     case WINED3DPOOL_MANAGED:
784         if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
785                                                 Usage of DYNAMIC which are mutually exclusive, not doing \
786                                                 anything just telling you.\n");
787     break;
788     case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
789         if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
790            && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
791             FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
792     break;
793     default:
794         FIXME("(%p) Unknown pool %d\n", This, Pool);
795     break;
796     };
797
798     if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
799         FIXME("Trying to create a render target that isn't in the default pool\n");
800     }
801
802
803     object->locked   = FALSE;
804     object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
805
806     /* mark the texture as dirty so that it get's loaded first time around*/
807     IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
808     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
809            This, Width, Height, Format, debug_d3dformat(Format),
810            (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
811     return WINED3D_OK;
812
813 }
814
815 HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
816                                                  DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
817                                                  IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
818                                                  D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
819
820     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
821     IWineD3DTextureImpl *object;
822     unsigned int i;
823     UINT tmpW;
824     UINT tmpH;
825     HRESULT hr;
826     unsigned int pow2Width  = Width;
827     unsigned int pow2Height = Height;
828
829
830     TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
831
832     /* TODO: It should only be possible to create textures for formats 
833              that are reported as supported */
834     if (WINED3DFMT_UNKNOWN >= Format) {
835         WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
836         return WINED3DERR_INVALIDCALL;
837     }
838
839     D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
840     D3DINITIALIZEBASETEXTURE(object->baseTexture);    
841     object->width  = Width;
842     object->height = Height;
843
844     /** Non-power2 support **/
845     /* Find the nearest pow2 match */
846     pow2Width = pow2Height = 1;
847     while (pow2Width < Width) pow2Width <<= 1;
848     while (pow2Height < Height) pow2Height <<= 1;
849
850     /** FIXME: add support for real non-power-two if it's provided by the video card **/
851     /* Precalculated scaling for 'faked' non power of two texture coords */
852     object->pow2scalingFactorX  =  (((float)Width)  / ((float)pow2Width));
853     object->pow2scalingFactorY  =  (((float)Height) / ((float)pow2Height));
854     TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
855
856     /* Calculate levels for mip mapping */
857     if (Levels == 0) {
858         TRACE("calculating levels %d\n", object->baseTexture.levels);
859         object->baseTexture.levels++;
860         tmpW = Width;
861         tmpH = Height;
862         while (tmpW > 1 && tmpH > 1) {
863             tmpW = max(1, tmpW >> 1);
864             tmpH = max(1, tmpH >> 1);
865             object->baseTexture.levels++;
866         }
867         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
868     }
869
870     /* Generate all the surfaces */
871     tmpW = Width;
872     tmpH = Height;
873     for (i = 0; i < object->baseTexture.levels; i++)
874     {
875         /* use the callback to create the texture surface */
876         hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
877         if (hr!= WINED3D_OK) {
878             int j;
879             FIXME("Failed to create surface  %p\n", object);
880             /* clean up */
881             for (j = 0 ; j < i ; j++) {
882                 IWineD3DSurface_Release(object->surfaces[j]);
883             }
884             /* heap free object */
885             HeapFree(GetProcessHeap(), 0, object);
886
887             *ppTexture = NULL;
888             return hr;
889         }
890
891         IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
892         TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
893         /* calculate the next mipmap level */
894         tmpW = max(1, tmpW >> 1);
895         tmpH = max(1, tmpH >> 1);
896     }
897
898     TRACE("(%p) : Created  texture %p\n", This, object);
899     return WINED3D_OK;
900 }
901
902 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
903                                                       UINT Width, UINT Height, UINT Depth,
904                                                       UINT Levels, DWORD Usage,
905                                                       WINED3DFORMAT Format, WINED3DPOOL Pool,
906                                                       IWineD3DVolumeTexture **ppVolumeTexture,
907                                                       HANDLE *pSharedHandle, IUnknown *parent,
908                                                       D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
909
910     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
911     IWineD3DVolumeTextureImpl *object;
912     unsigned int               i;
913     UINT                       tmpW;
914     UINT                       tmpH;
915     UINT                       tmpD;
916
917     /* TODO: It should only be possible to create textures for formats 
918              that are reported as supported */
919     if (WINED3DFMT_UNKNOWN >= Format) {
920         WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
921         return WINED3DERR_INVALIDCALL;
922     }
923
924     D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
925     D3DINITIALIZEBASETEXTURE(object->baseTexture);
926
927     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
928           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
929
930     object->width  = Width;
931     object->height = Height;
932     object->depth  = Depth;
933
934     /* Calculate levels for mip mapping */
935     if (Levels == 0) {
936         object->baseTexture.levels++;
937         tmpW = Width;
938         tmpH = Height;
939         tmpD = Depth;
940         while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
941             tmpW = max(1, tmpW >> 1);
942             tmpH = max(1, tmpH >> 1);
943             tmpD = max(1, tmpD >> 1);
944             object->baseTexture.levels++;
945         }
946         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
947     }
948
949     /* Generate all the surfaces */
950     tmpW = Width;
951     tmpH = Height;
952     tmpD = Depth;
953
954     for (i = 0; i < object->baseTexture.levels; i++)
955     {
956         /* Create the volume */
957         D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
958                            (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
959
960         /* Set it's container to this object */
961         IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
962
963         /* calcualte the next mipmap level */
964         tmpW = max(1, tmpW >> 1);
965         tmpH = max(1, tmpH >> 1);
966         tmpD = max(1, tmpD >> 1);
967     }
968
969     *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
970     TRACE("(%p) : Created volume texture %p\n", This, object);
971     return WINED3D_OK;
972 }
973
974 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
975                                                UINT Width, UINT Height, UINT Depth,
976                                                DWORD Usage,
977                                                WINED3DFORMAT Format, WINED3DPOOL Pool,
978                                                IWineD3DVolume** ppVolume,
979                                                HANDLE* pSharedHandle, IUnknown *parent) {
980
981     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
982     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
983
984     D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
985
986     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
987           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
988
989     object->currentDesc.Width   = Width;
990     object->currentDesc.Height  = Height;
991     object->currentDesc.Depth   = Depth;
992     object->bytesPerPixel       = D3DFmtGetBpp(This, Format);
993
994     /** Note: Volume textures cannot be dxtn, hence no need to check here **/
995     object->lockable            = TRUE;
996     object->locked              = FALSE;
997     memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
998     object->dirty               = TRUE;
999
1000     return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1001 }
1002
1003 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1004                                                     UINT Levels, DWORD Usage,
1005                                                     WINED3DFORMAT Format, WINED3DPOOL Pool,
1006                                                     IWineD3DCubeTexture **ppCubeTexture,
1007                                                     HANDLE *pSharedHandle, IUnknown *parent,
1008                                                     D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1009
1010     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1011     IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1012     unsigned int             i, j;
1013     UINT                     tmpW;
1014     HRESULT                  hr;
1015     unsigned int pow2EdgeLength  = EdgeLength;
1016
1017     /* TODO: It should only be possible to create textures for formats 
1018              that are reported as supported */
1019     if (WINED3DFMT_UNKNOWN >= Format) {
1020         WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1021         return WINED3DERR_INVALIDCALL;
1022     }
1023
1024     D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1025     D3DINITIALIZEBASETEXTURE(object->baseTexture);
1026
1027     TRACE("(%p) Create Cube Texture\n", This);
1028
1029     /** Non-power2 support **/
1030
1031     /* Find the nearest pow2 match */
1032     pow2EdgeLength = 1;
1033     while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1034
1035     object->edgeLength           = EdgeLength;
1036     /* TODO: support for native non-power 2 */
1037     /* Precalculated scaling for 'faked' non power of two texture coords */
1038     object->pow2scalingFactor    = ((float)EdgeLength) / ((float)pow2EdgeLength);
1039
1040     /* Calculate levels for mip mapping */
1041     if (Levels == 0) {
1042         object->baseTexture.levels++;
1043         tmpW = EdgeLength;
1044         while (tmpW > 1) {
1045             tmpW = max(1, tmpW >> 1);
1046             object->baseTexture.levels++;
1047         }
1048         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1049     }
1050
1051     /* Generate all the surfaces */
1052     tmpW = EdgeLength;
1053     for (i = 0; i < object->baseTexture.levels; i++) {
1054
1055         /* Create the 6 faces */
1056         for (j = 0; j < 6; j++) {
1057
1058             hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1059                                    i /* Level */, &object->surfaces[j][i],pSharedHandle);
1060
1061             if(hr!= WINED3D_OK) {
1062                 /* clean up */
1063                 int k;
1064                 int l;
1065                 for (l = 0; l < j; l++) {
1066                     IWineD3DSurface_Release(object->surfaces[j][i]);
1067                 }
1068                 for (k = 0; k < i; k++) {
1069                     for (l = 0; l < 6; l++) {
1070                     IWineD3DSurface_Release(object->surfaces[l][j]);
1071                     }
1072                 }
1073
1074                 FIXME("(%p) Failed to create surface\n",object);
1075                 HeapFree(GetProcessHeap(),0,object);
1076                 *ppCubeTexture = NULL;
1077                 return hr;
1078             }
1079             IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1080             TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1081         }
1082         tmpW = max(1, tmpW >> 1);
1083     }
1084
1085     TRACE("(%p) : Created Cube Texture %p\n", This, object);
1086     *ppCubeTexture = (IWineD3DCubeTexture *) object;
1087     return WINED3D_OK;
1088 }
1089
1090 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1091     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1092     IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1093
1094     if (NULL == ppQuery) {
1095         /* Just a check to see if we support this type of query */
1096         HRESULT hr = WINED3DERR_NOTAVAILABLE;
1097         switch(Type) {
1098         case WINED3DQUERYTYPE_OCCLUSION:
1099             TRACE("(%p) occlusion query\n", This);
1100             if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1101                 hr = WINED3D_OK;
1102             else
1103                 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1104             break;
1105         case WINED3DQUERYTYPE_VCACHE:
1106         case WINED3DQUERYTYPE_RESOURCEMANAGER:
1107         case WINED3DQUERYTYPE_VERTEXSTATS:
1108         case WINED3DQUERYTYPE_EVENT:
1109         case WINED3DQUERYTYPE_TIMESTAMP:
1110         case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1111         case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1112         case WINED3DQUERYTYPE_PIPELINETIMINGS:
1113         case WINED3DQUERYTYPE_INTERFACETIMINGS:
1114         case WINED3DQUERYTYPE_VERTEXTIMINGS:
1115         case WINED3DQUERYTYPE_PIXELTIMINGS:
1116         case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1117         case WINED3DQUERYTYPE_CACHEUTILIZATION:
1118         default:
1119             FIXME("(%p) Unhandled query type %d\n", This, Type);
1120         }
1121         return hr;
1122     }
1123
1124     D3DCREATEOBJECTINSTANCE(object, Query)
1125     object->type         = Type;
1126     /* allocated the 'extended' data based on the type of query requested */
1127     switch(Type){
1128     case D3DQUERYTYPE_OCCLUSION:
1129         if(GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY)) {
1130             TRACE("(%p) Allocating data for an occlusion query\n", This);
1131             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1132             break;
1133         }
1134     case D3DQUERYTYPE_VCACHE:
1135     case D3DQUERYTYPE_RESOURCEMANAGER:
1136     case D3DQUERYTYPE_VERTEXSTATS:
1137     case D3DQUERYTYPE_EVENT:
1138     case D3DQUERYTYPE_TIMESTAMP:
1139     case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1140     case D3DQUERYTYPE_TIMESTAMPFREQ:
1141     case D3DQUERYTYPE_PIPELINETIMINGS:
1142     case D3DQUERYTYPE_INTERFACETIMINGS:
1143     case D3DQUERYTYPE_VERTEXTIMINGS:
1144     case D3DQUERYTYPE_PIXELTIMINGS:
1145     case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1146     case D3DQUERYTYPE_CACHEUTILIZATION:
1147     default:
1148         object->extendedData = 0;
1149         FIXME("(%p) Unhandled query type %d\n",This , Type);
1150     }
1151     TRACE("(%p) : Created Query %p\n", This, object);
1152     return WINED3D_OK;
1153 }
1154
1155 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1156 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS*  pPresentationParameters,                                                                   IWineD3DSwapChain** ppSwapChain,
1157                                                             IUnknown* parent,
1158                                                             D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1159                                                             D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1160     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1161
1162     HDC                     hDc;
1163     IWineD3DSwapChainImpl  *object; /** NOTE: impl ref allowed since this is a create function **/
1164     int                     num;
1165     XVisualInfo             template;
1166     GLXContext              oldContext;
1167     Drawable                oldDrawable;
1168     HRESULT                 hr = WINED3D_OK;
1169
1170     TRACE("(%p) : Created Aditional Swap Chain\n", This);
1171
1172    /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1173    * does a device hold a reference to a swap chain giving them a lifetime of the device
1174    * or does the swap chain notify the device of its destruction.
1175     *******************************/
1176
1177     D3DCREATEOBJECTINSTANCE(object, SwapChain)
1178
1179     /* Initialize other useful values */
1180     object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1181
1182     /*********************
1183     * Lookup the window Handle and the relating X window handle
1184     ********************/
1185
1186     /* Setup hwnd we are using, plus which display this equates to */
1187     object->win_handle = *(pPresentationParameters->hDeviceWindow);
1188     if (!object->win_handle) {
1189         object->win_handle = This->createParms.hFocusWindow;
1190     }
1191
1192     object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1193     if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1194         ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1195         return WINED3DERR_NOTAVAILABLE;
1196     }
1197     hDc                = GetDC(object->win_handle);
1198     object->display    = get_display(hDc);
1199     ReleaseDC(object->win_handle, hDc);
1200     TRACE("Using a display of %p %p\n", object->display, hDc);
1201
1202     if (NULL == object->display || NULL == hDc) {
1203         WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1204         return WINED3DERR_NOTAVAILABLE;
1205     }
1206
1207     if (object->win == 0) {
1208         WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1209         return WINED3DERR_NOTAVAILABLE;
1210     }
1211     /**
1212     * Create an opengl context for the display visual
1213     *  NOTE: the visual is chosen as the window is created and the glcontext cannot
1214     *     use different properties after that point in time. FIXME: How to handle when requested format
1215     *     doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1216     *     it chooses is identical to the one already being used!
1217      **********************************/
1218
1219     /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1220     ENTER_GL();
1221
1222     /* Create a new context for this swapchain */
1223     template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1224     /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1225     (or the best possible if none is requested) */
1226     TRACE("Found x visual ID  : %ld\n", template.visualid);
1227
1228     object->visInfo   = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1229     if (NULL == object->visInfo) {
1230         ERR("cannot really get XVisual\n");
1231         LEAVE_GL();
1232         return WINED3DERR_NOTAVAILABLE;
1233     } else {
1234         int n, value;
1235         /* Write out some debug info about the visual/s */
1236         TRACE("Using x visual ID  : %ld\n", template.visualid);
1237         TRACE("        visual info: %p\n", object->visInfo);
1238         TRACE("        num items  : %d\n", num);
1239         for (n = 0;n < num; n++) {
1240             TRACE("=====item=====: %d\n", n + 1);
1241             TRACE("   visualid      : %ld\n", object->visInfo[n].visualid);
1242             TRACE("   screen        : %d\n",  object->visInfo[n].screen);
1243             TRACE("   depth         : %u\n",  object->visInfo[n].depth);
1244             TRACE("   class         : %d\n",  object->visInfo[n].class);
1245             TRACE("   red_mask      : %ld\n", object->visInfo[n].red_mask);
1246             TRACE("   green_mask    : %ld\n", object->visInfo[n].green_mask);
1247             TRACE("   blue_mask     : %ld\n", object->visInfo[n].blue_mask);
1248             TRACE("   colormap_size : %d\n",  object->visInfo[n].colormap_size);
1249             TRACE("   bits_per_rgb  : %d\n",  object->visInfo[n].bits_per_rgb);
1250             /* log some extra glx info */
1251             glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1252             TRACE("   gl_aux_buffers  : %d\n",  value);
1253             glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1254             TRACE("   gl_buffer_size  : %d\n",  value);
1255             glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1256             TRACE("   gl_red_size  : %d\n",  value);
1257             glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1258             TRACE("   gl_green_size  : %d\n",  value);
1259             glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1260             TRACE("   gl_blue_size  : %d\n",  value);
1261             glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1262             TRACE("   gl_alpha_size  : %d\n",  value);
1263             glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1264             TRACE("   gl_depth_size  : %d\n",  value);
1265             glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1266             TRACE("   gl_stencil_size : %d\n",  value);
1267         }
1268         /* Now choose a simila visual ID*/
1269     }
1270 #ifdef USE_CONTEXT_MANAGER
1271
1272     /** TODO: use a context mamager **/
1273 #endif
1274
1275     {
1276         IWineD3DSwapChain *implSwapChain;
1277         if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1278             /* The first time around we create the context that is shared with all other swapchains and render targets */
1279             object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1280             TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1281         } else {
1282
1283             TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1284             /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1285             /* and create a new context with the implicit swapchains context as the shared context */
1286             object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1287             IWineD3DSwapChain_Release(implSwapChain);
1288         }
1289     }
1290
1291     /* Cleanup */
1292     XFree(object->visInfo);
1293     object->visInfo = NULL;
1294
1295     if (NULL == object->glCtx) {
1296         ERR("cannot create glxContext\n");
1297         LEAVE_GL();
1298         return WINED3DERR_NOTAVAILABLE;
1299     }
1300
1301     LEAVE_GL();
1302     if (object->glCtx == NULL) {
1303         ERR("Error in context creation !\n");
1304         return WINED3DERR_INVALIDCALL;
1305     } else {
1306         TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1307                 object->win_handle, object->glCtx, object->win, object->visInfo);
1308     }
1309
1310    /*********************
1311    * Windowed / Fullscreen
1312    *******************/
1313
1314    /**
1315    * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1316    * so we should really check to see if there is a fullscreen swapchain already
1317    * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1318     **************************************/
1319
1320    if (!*(pPresentationParameters->Windowed)) {
1321
1322         DEVMODEW devmode;
1323         HDC      hdc;
1324         int      bpp = 0;
1325
1326         /* Get info on the current display setup */
1327         hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1328         bpp = GetDeviceCaps(hdc, BITSPIXEL);
1329         DeleteDC(hdc);
1330
1331         /* Change the display settings */
1332         memset(&devmode, 0, sizeof(DEVMODEW));
1333         devmode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1334         devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1335         devmode.dmPelsWidth  = *(pPresentationParameters->BackBufferWidth);
1336         devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1337         MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1338         ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1339
1340         /* Make popup window */
1341         SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1342         SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1343                      *(pPresentationParameters->BackBufferWidth),
1344                      *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1345
1346
1347     }
1348
1349
1350     /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1351      *  then the corresponding dimension of the client area of the hDeviceWindow
1352      *  (or the focus window, if hDeviceWindow is NULL) is taken.
1353       **********************/
1354
1355     if (*(pPresentationParameters->Windowed) &&
1356         ((*(pPresentationParameters->BackBufferWidth)  == 0) ||
1357          (*(pPresentationParameters->BackBufferHeight) == 0))) {
1358
1359         RECT Rect;
1360         GetClientRect(object->win_handle, &Rect);
1361
1362         if (*(pPresentationParameters->BackBufferWidth) == 0) {
1363            *(pPresentationParameters->BackBufferWidth) = Rect.right;
1364            TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1365         }
1366         if (*(pPresentationParameters->BackBufferHeight) == 0) {
1367            *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1368            TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1369         }
1370     }
1371
1372    /*********************
1373    * finish off parameter initialization
1374    *******************/
1375
1376     /* Put the correct figures in the presentation parameters */
1377     TRACE("Coppying accross presentaion paraneters\n");
1378     object->presentParms.BackBufferWidth                = *(pPresentationParameters->BackBufferWidth);
1379     object->presentParms.BackBufferHeight               = *(pPresentationParameters->BackBufferHeight);
1380     object->presentParms.BackBufferFormat               = *(pPresentationParameters->BackBufferFormat);
1381     object->presentParms.BackBufferCount                = *(pPresentationParameters->BackBufferCount);
1382     object->presentParms.MultiSampleType                = *(pPresentationParameters->MultiSampleType);
1383     object->presentParms.MultiSampleQuality             = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1384     object->presentParms.SwapEffect                     = *(pPresentationParameters->SwapEffect);
1385     object->presentParms.hDeviceWindow                  = *(pPresentationParameters->hDeviceWindow);
1386     object->presentParms.Windowed                       = *(pPresentationParameters->Windowed);
1387     object->presentParms.EnableAutoDepthStencil         = *(pPresentationParameters->EnableAutoDepthStencil);
1388     object->presentParms.AutoDepthStencilFormat         = *(pPresentationParameters->AutoDepthStencilFormat);
1389     object->presentParms.Flags                          = *(pPresentationParameters->Flags);
1390     object->presentParms.FullScreen_RefreshRateInHz     = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1391     object->presentParms.PresentationInterval           = *(pPresentationParameters->PresentationInterval);
1392
1393
1394    /*********************
1395    * Create the back, front and stencil buffers
1396    *******************/
1397     TRACE("calling rendertarget CB\n");
1398     hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1399                              object->presentParms.BackBufferWidth,
1400                              object->presentParms.BackBufferHeight,
1401                              object->presentParms.BackBufferFormat,
1402                              object->presentParms.MultiSampleType,
1403                              object->presentParms.MultiSampleQuality,
1404                              TRUE /* Lockable */,
1405                              &object->frontBuffer,
1406                              NULL /* pShared (always null)*/);
1407     if (object->frontBuffer != NULL)
1408         IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1409     TRACE("calling rendertarget CB\n");
1410     hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1411                              object->presentParms.BackBufferWidth,
1412                              object->presentParms.BackBufferHeight,
1413                              object->presentParms.BackBufferFormat,
1414                              object->presentParms.MultiSampleType,
1415                              object->presentParms.MultiSampleQuality,
1416                              TRUE /* Lockable */,
1417                              &object->backBuffer,
1418                              NULL /* pShared (always null)*/);
1419     if (object->backBuffer != NULL)
1420         IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
1421
1422     /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1423     if (pPresentationParameters->EnableAutoDepthStencil) {
1424         TRACE("Creating depth stencil buffer\n");
1425         if (This->depthStencilBuffer == NULL ) {
1426             hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1427                                     object->presentParms.BackBufferWidth,
1428                                     object->presentParms.BackBufferHeight,
1429                                     object->presentParms.AutoDepthStencilFormat,
1430                                     object->presentParms.MultiSampleType,
1431                                     object->presentParms.MultiSampleQuality,
1432                                     FALSE /* FIXME: Discard */,
1433                                     &This->depthStencilBuffer,
1434                                     NULL /* pShared (always null)*/  );
1435             if (This->depthStencilBuffer != NULL)
1436                 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1437         }
1438
1439         /** TODO: A check on width, height and multisample types
1440         *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1441          ****************************/
1442         object->wantsDepthStencilBuffer = TRUE;
1443     } else {
1444         object->wantsDepthStencilBuffer = FALSE;
1445     }
1446
1447     TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1448
1449
1450    /*********************
1451    * init the default renderTarget management
1452    *******************/
1453     object->drawable     = object->win;
1454     object->render_ctx   = object->glCtx;
1455
1456     if (hr == WINED3D_OK) {
1457         /*********************
1458          * Setup some defaults and clear down the buffers
1459          *******************/
1460         ENTER_GL();
1461         /** save current context and drawable **/
1462         oldContext  = glXGetCurrentContext();
1463         oldDrawable = glXGetCurrentDrawable();
1464
1465         TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1466         if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1467             ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1468         }
1469         checkGLcall("glXMakeCurrent");
1470
1471         TRACE("Setting up the screen\n");
1472         /* Clear the screen */
1473         glClearColor(1.0, 0.0, 0.0, 0.0);
1474         checkGLcall("glClearColor");
1475         glClearIndex(0);
1476         glClearDepth(1);
1477         glClearStencil(0xffff);
1478
1479         checkGLcall("glClear");
1480
1481         glColor3f(1.0, 1.0, 1.0);
1482         checkGLcall("glColor3f");
1483
1484         glEnable(GL_LIGHTING);
1485         checkGLcall("glEnable");
1486
1487         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1488         checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1489
1490         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1491         checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1492
1493         glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1494         checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1495
1496         /* switch back to the original context (if there was one)*/
1497         if (This->swapchains != NULL) {
1498             /** TODO: restore the context and drawable **/
1499             glXMakeCurrent(object->display, oldDrawable, oldContext);
1500         }
1501
1502         LEAVE_GL();
1503
1504         { /* Finally add the swapchain to the end of the devices' swapchain list */
1505             SwapChainList **nextSwapchain;
1506             nextSwapchain = &This->swapchains;
1507             while (*nextSwapchain != NULL) {
1508                 nextSwapchain = &((*nextSwapchain)->next);
1509             }
1510             (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1511             (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1512         }
1513         TRACE("Set swapchain to %p\n", object);
1514     } else { /* something went wrong so clean up */
1515         IUnknown* bufferParent;
1516         if (object->frontBuffer) {
1517
1518             IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1519             IUnknown_Release(bufferParent); /* once for the get parent */
1520             if (IUnknown_Release(bufferParent) > 0) {
1521                 FIXME("(%p) Something's still holding the front buffer\n",This);
1522             }
1523         }
1524         if (object->backBuffer) {
1525             IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1526             IUnknown_Release(bufferParent); /* once for the get parent */
1527             if (IUnknown_Release(bufferParent) > 0) {
1528                 FIXME("(%p) Something's still holding the back buffer\n",This);
1529             }
1530         }
1531         /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1532         /* Clean up the context */
1533         /* check that we are the current context first (we shouldn't be though!) */
1534         if (object->glCtx != 0) {
1535             if(glXGetCurrentContext() == object->glCtx) {
1536                 glXMakeCurrent(object->display, None, NULL);
1537             }
1538             glXDestroyContext(object->display, object->glCtx);
1539         }
1540         HeapFree(GetProcessHeap(), 0, object);
1541
1542     }
1543
1544     return hr;
1545 }
1546
1547 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1548 UINT     WINAPI  IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1549     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1550     unsigned int numberOfSwapChains = 0;
1551     SwapChainList          *swapchain;
1552
1553     swapchain = This->swapchains;
1554     /* itterate through the list to get a count */
1555     while (swapchain != NULL) {
1556         swapchain = swapchain->next;
1557         numberOfSwapChains++;
1558     }
1559
1560     TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1561     return numberOfSwapChains;
1562 }
1563
1564 HRESULT  WINAPI  IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1565     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1566     SwapChainList *swapchain;
1567     int i = iSwapChain;
1568     HRESULT hr = WINED3DERR_INVALIDCALL;
1569     swapchain = This->swapchains;
1570     TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1571
1572
1573     TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1574     while (i > 0 && swapchain != NULL) {
1575         swapchain = swapchain->next;
1576         --i;
1577     }
1578
1579     if (i > 0) {
1580         FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1581         *pSwapChain = NULL;
1582     } else if (swapchain != NULL) {
1583         /** TODO: move off to a linkesList implementation **/
1584         *pSwapChain = swapchain->swapchain;
1585         IWineD3DSwapChain_AddRef(*pSwapChain);
1586         hr = WINED3D_OK;
1587     }
1588
1589     TRACE("(%p) returning %p\n", This, *pSwapChain);
1590     return hr;
1591 }
1592
1593 /*****
1594  * Vertex Declaration
1595  *****/
1596 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1597     IWineD3DDeviceImpl            *This   = (IWineD3DDeviceImpl *)iface;
1598     IWineD3DVertexDeclarationImpl *object = NULL;
1599     HRESULT hr = WINED3D_OK;
1600     TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1601     D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1602     object->allFVF = 0;
1603
1604     hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1605
1606     return hr;
1607 }
1608
1609 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1610 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1611     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1612     IWineD3DVertexShaderImpl *object;  /* NOTE: impl usage is ok, this is a create */
1613     HRESULT hr = WINED3D_OK;
1614     D3DCREATEOBJECTINSTANCE(object, VertexShader)
1615     object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1616
1617     TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1618
1619     /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1620     /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1621     if (pDeclaration != NULL) {
1622         IWineD3DVertexDeclaration *vertexDeclaration;
1623         hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1624         if (WINED3D_OK == hr) {
1625             TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1626             object->vertexDeclaration = vertexDeclaration;
1627         } else {
1628             FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1629             IWineD3DVertexShader_Release(*ppVertexShader);
1630             return WINED3DERR_INVALIDCALL;
1631         }
1632     }
1633
1634     hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1635
1636     if (WINED3D_OK != hr) {
1637         FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1638         IWineD3DVertexShader_Release(*ppVertexShader);
1639         return WINED3DERR_INVALIDCALL;
1640     }
1641
1642 #if 0 /* TODO: In D3D* SVP is atatched to the shader, in D3D9 it's attached to the device and isn't stored in the stateblock. */
1643     if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1644         /* Foo */
1645     } else {
1646         /* Bar */
1647     }
1648
1649 #endif
1650
1651     return WINED3D_OK;
1652 }
1653
1654 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1655     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1656     IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1657     HRESULT hr = WINED3D_OK;
1658
1659     D3DCREATEOBJECTINSTANCE(object, PixelShader)
1660     object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1661     hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1662     if (WINED3D_OK == hr) {
1663         TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1664     } else {
1665         WARN("(%p) : Failed to create pixel shader\n", This);
1666     }
1667
1668     return hr;
1669 }
1670
1671 HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1672     FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
1673     return WINED3DERR_INVALIDCALL;
1674 }
1675
1676 HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
1677     FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
1678     return WINED3DERR_INVALIDCALL;
1679 }
1680
1681 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1682    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1683    *ppD3D= This->wineD3D;
1684    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
1685    IWineD3D_AddRef(*ppD3D);
1686    return WINED3D_OK;
1687 }
1688
1689 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1690     /** NOTE: There's a probably  a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1691     * Into the video ram as possible and seeing how many fit
1692     * you can also get the correct initial value from via X and ATI's driver
1693     *******************/
1694     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1695     static BOOL showfixmes = TRUE;
1696     if (showfixmes) {
1697         FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1698          ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1699          showfixmes = FALSE;
1700     }
1701     TRACE("(%p) :  emulating %dMib for now, returning %dMib\n",  This, (emulated_textureram/(1024*1024)),
1702          ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1703     /* videomemory is simulated videomemory + AGP memory left */
1704     return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1705 }
1706
1707
1708
1709 /*****
1710  * Get / Set FVF
1711  *****/
1712 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1713     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1714     HRESULT hr = WINED3D_OK;
1715
1716     /* Update the current state block */
1717     This->updateStateBlock->fvf              = fvf;
1718     This->updateStateBlock->changed.fvf      = TRUE;
1719     This->updateStateBlock->set.fvf          = TRUE;
1720
1721     TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1722
1723     if (0 != fvf) {
1724         /* clear down the vertex declaration
1725          NOTE: Axis and Allies doesn't work properly otherwise
1726          (may be a stateblock problem though!)
1727         */
1728       hr = IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1729     }
1730
1731     return hr;
1732 }
1733
1734
1735 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1736     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1737     TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1738     *pfvf = This->stateBlock->fvf;
1739     return WINED3D_OK;
1740 }
1741
1742 /*****
1743  * Get / Set Stream Source
1744  *****/
1745 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1746         IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1747     IWineD3DVertexBuffer     *oldSrc;
1748
1749     /**TODO: instance and index data, see
1750     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1751     and
1752     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
1753      **************/
1754
1755     /* D3d9 only, but shouldn't  hurt d3d8 */
1756     UINT streamFlags;
1757
1758     streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1759     if (streamFlags) {
1760         if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1761            FIXME("stream index data not supported\n");
1762         }
1763         if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1764            FIXME("stream instance data not supported\n");
1765         }
1766     }
1767
1768     StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1769
1770     if (StreamNumber >= MAX_STREAMS) {
1771         WARN("Stream out of range %d\n", StreamNumber);
1772         return WINED3DERR_INVALIDCALL;
1773     }
1774
1775     oldSrc = This->stateBlock->streamSource[StreamNumber];
1776     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1777
1778     This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1779     This->updateStateBlock->set.streamSource[StreamNumber]     = TRUE;
1780     This->updateStateBlock->streamStride[StreamNumber]         = Stride;
1781     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
1782     This->updateStateBlock->streamOffset[StreamNumber]         = OffsetInBytes;
1783     This->updateStateBlock->streamFlags[StreamNumber]          = streamFlags;
1784
1785     /* Handle recording of state blocks */
1786     if (This->isRecordingState) {
1787         TRACE("Recording... not performing anything\n");
1788         return WINED3D_OK;
1789     }
1790
1791     /* Not recording... */
1792     /* Need to do a getParent and pass the reffs up */
1793     /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1794     which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1795     so for now, just count internally   */
1796     if (pStreamData != NULL) {
1797         IWineD3DVertexBuffer_AddRef(pStreamData);
1798     }
1799     if (oldSrc != NULL) {
1800         IWineD3DVertexBuffer_Release(oldSrc);
1801     }
1802
1803     return WINED3D_OK;
1804 }
1805
1806 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1807     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1808     UINT streamFlags;
1809
1810     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
1811            This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1812
1813
1814     streamFlags = StreamNumber &(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1815     if (streamFlags) {
1816         if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1817            FIXME("stream index data not supported\n");
1818         }
1819         if (streamFlags & D3DSTREAMSOURCE_INDEXEDDATA) {
1820             FIXME("stream instance data not supported\n");
1821         }
1822     }
1823
1824     StreamNumber&= ~(D3DSTREAMSOURCE_INDEXEDDATA | D3DSTREAMSOURCE_INSTANCEDATA);
1825
1826     if (StreamNumber >= MAX_STREAMS) {
1827         WARN("Stream out of range %d\n", StreamNumber);
1828         return WINED3DERR_INVALIDCALL;
1829     }
1830     *pStream = This->stateBlock->streamSource[StreamNumber];
1831     *pStride = This->stateBlock->streamStride[StreamNumber];
1832     *pOffset = This->stateBlock->streamOffset[StreamNumber];
1833
1834      if (*pStream == NULL) {
1835         FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
1836         return  WINED3DERR_INVALIDCALL;
1837     }
1838
1839     IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1840     return WINED3D_OK;
1841 }
1842
1843 /*Should be quite easy, just an extension of vertexdata
1844 ref...
1845 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1846
1847 The divider is a bit odd though
1848
1849 VertexOffset = StartVertex / Divider * StreamStride +
1850                VertexIndex / Divider * StreamStride + StreamOffset
1851
1852 */
1853 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
1854     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1855
1856     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
1857     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (D3DSTREAMSOURCE_INSTANCEDATA  | D3DSTREAMSOURCE_INDEXEDDATA );
1858
1859     This->updateStateBlock->changed.streamFreq[StreamNumber]  = TRUE;
1860     This->updateStateBlock->set.streamFreq[StreamNumber]      = TRUE;
1861     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
1862
1863     if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
1864         FIXME("Stream indexing not fully supported\n");
1865     }
1866
1867     return WINED3D_OK;
1868 }
1869
1870 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
1871     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1872
1873     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
1874     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
1875
1876     TRACE("(%p) : returning %d\n", This, *Divider);
1877
1878     return WINED3D_OK;
1879 }
1880
1881 /*****
1882  * Get / Set & Multiply Transform
1883  *****/
1884 HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1885     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1886
1887     /* Most of this routine, comments included copied from ddraw tree initially: */
1888     TRACE("(%p) : Transform State=%d\n", This, d3dts);
1889
1890     /* Handle recording of state blocks */
1891     if (This->isRecordingState) {
1892         TRACE("Recording... not performing anything\n");
1893         This->updateStateBlock->changed.transform[d3dts] = TRUE;
1894         This->updateStateBlock->set.transform[d3dts]     = TRUE;
1895         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1896         return WINED3D_OK;
1897     }
1898
1899     /*
1900      * If the new matrix is the same as the current one,
1901      * we cut off any further processing. this seems to be a reasonable
1902      * optimization because as was noticed, some apps (warcraft3 for example)
1903      * tend towards setting the same matrix repeatedly for some reason.
1904      *
1905      * From here on we assume that the new matrix is different, wherever it matters.
1906      */
1907     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1908         TRACE("The app is setting the same matrix over again\n");
1909         return WINED3D_OK;
1910     } else {
1911         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1912     }
1913
1914     /*
1915        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1916        where ViewMat = Camera space, WorldMat = world space.
1917
1918        In OpenGL, camera and world space is combined into GL_MODELVIEW
1919        matrix.  The Projection matrix stay projection matrix.
1920      */
1921
1922     /* Capture the times we can just ignore the change for now */
1923     if (d3dts == D3DTS_WORLDMATRIX(0)) {
1924         This->modelview_valid = FALSE;
1925         return WINED3D_OK;
1926
1927     } else if (d3dts == D3DTS_PROJECTION) {
1928         This->proj_valid = FALSE;
1929         return WINED3D_OK;
1930
1931     } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1932         /* Indexed Vertex Blending Matrices 256 -> 511  */
1933         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1934         FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1935         return WINED3D_OK;
1936     }
1937
1938     /* Now we really are going to have to change a matrix */
1939     ENTER_GL();
1940
1941     if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1942         /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1943     } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1944         unsigned int k;
1945
1946         /* If we are changing the View matrix, reset the light and clipping planes to the new view
1947          * NOTE: We have to reset the positions even if the light/plane is not currently
1948          *       enabled, since the call to enable it will not reset the position.
1949          * NOTE2: Apparently texture transforms do NOT need reapplying
1950          */
1951
1952         PLIGHTINFOEL *lightChain = NULL;
1953         This->modelview_valid = FALSE;
1954         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1955
1956         glMatrixMode(GL_MODELVIEW);
1957         checkGLcall("glMatrixMode(GL_MODELVIEW)");
1958         glPushMatrix();
1959         glLoadMatrixf((float *)lpmatrix);
1960         checkGLcall("glLoadMatrixf(...)");
1961
1962         /* Reset lights */
1963         lightChain = This->stateBlock->lights;
1964         while (lightChain && lightChain->glIndex != -1) {
1965             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1966             checkGLcall("glLightfv posn");
1967             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1968             checkGLcall("glLightfv dirn");
1969             lightChain = lightChain->next;
1970         }
1971
1972         /* Reset Clipping Planes if clipping is enabled */
1973         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1974             glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1975             checkGLcall("glClipPlane");
1976         }
1977         glPopMatrix();
1978
1979     } else { /* What was requested!?? */
1980         WARN("invalid matrix specified: %i\n", d3dts);
1981     }
1982
1983     /* Release lock, all done */
1984     LEAVE_GL();
1985     return WINED3D_OK;
1986
1987 }
1988 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1989     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1990     TRACE("(%p) : for Transform State %d\n", This, State);
1991     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1992     return WINED3D_OK;
1993 }
1994
1995 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1996     D3DMATRIX *mat = NULL;
1997     D3DMATRIX temp;
1998
1999     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2000      * below means it will be recorded in a state block change, but it
2001      * works regardless where it is recorded.
2002      * If this is found to be wrong, change to StateBlock.
2003      */
2004     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2005     TRACE("(%p) : For state %u\n", This, State);
2006
2007     if (State < HIGHEST_TRANSFORMSTATE)
2008     {
2009         mat = &This->updateStateBlock->transforms[State];
2010     } else {
2011         FIXME("Unhandled transform state!!\n");
2012     }
2013
2014     /* Copied from ddraw code:  */
2015     temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
2016       (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2017     temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
2018       (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2019     temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
2020       (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2021     temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
2022       (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2023
2024     temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
2025       (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2026     temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
2027       (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2028     temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
2029       (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2030     temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
2031       (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2032
2033     temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
2034       (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2035     temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
2036       (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2037     temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
2038       (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2039     temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
2040       (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2041
2042     temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
2043       (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2044     temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
2045       (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2046     temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
2047       (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2048     temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
2049       (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2050
2051     /* Apply change via set transform - will reapply to eg. lights this way */
2052     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2053 }
2054
2055 /*****
2056  * Get / Set Light
2057  *   WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2058  *****/
2059 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2060    you can reference any indexes you want as long as that number max are enabled at any
2061    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2062    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2063    but when recording, just build a chain pretty much of commands to be replayed.                  */
2064
2065 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2066     float rho;
2067     PLIGHTINFOEL *object, *temp;
2068
2069     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2070     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2071
2072     /* If recording state block, just add to end of lights chain */
2073     if (This->isRecordingState) {
2074         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2075         if (NULL == object) {
2076             return WINED3DERR_OUTOFVIDEOMEMORY;
2077         }
2078         memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2079         object->OriginalIndex = Index;
2080         object->glIndex = -1;
2081         object->changed = TRUE;
2082
2083         /* Add to the END of the chain of lights changes to be replayed */
2084         if (This->updateStateBlock->lights == NULL) {
2085             This->updateStateBlock->lights = object;
2086         } else {
2087             temp = This->updateStateBlock->lights;
2088             while (temp->next != NULL) temp=temp->next;
2089             temp->next = object;
2090         }
2091         TRACE("Recording... not performing anything more\n");
2092         return WINED3D_OK;
2093     }
2094
2095     /* Ok, not recording any longer so do real work */
2096     object = This->stateBlock->lights;
2097     while (object != NULL && object->OriginalIndex != Index) object = object->next;
2098
2099     /* If we didn't find it in the list of lights, time to add it */
2100     if (object == NULL) {
2101         PLIGHTINFOEL *insertAt,*prevPos;
2102
2103         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2104         if (NULL == object) {
2105             return WINED3DERR_OUTOFVIDEOMEMORY;
2106         }
2107         object->OriginalIndex = Index;
2108         object->glIndex = -1;
2109
2110         /* Add it to the front of list with the idea that lights will be changed as needed
2111            BUT after any lights currently assigned GL indexes                             */
2112         insertAt = This->stateBlock->lights;
2113         prevPos  = NULL;
2114         while (insertAt != NULL && insertAt->glIndex != -1) {
2115             prevPos  = insertAt;
2116             insertAt = insertAt->next;
2117         }
2118
2119         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2120             This->stateBlock->lights = object;
2121         } else if (insertAt == NULL) { /* End of list */
2122             prevPos->next = object;
2123             object->prev = prevPos;
2124         } else { /* Middle of chain */
2125             if (prevPos == NULL) {
2126                 This->stateBlock->lights = object;
2127             } else {
2128                 prevPos->next = object;
2129             }
2130             object->prev = prevPos;
2131             object->next = insertAt;
2132             insertAt->prev = object;
2133         }
2134     }
2135
2136     /* Initialize the object */
2137     TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2138           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2139           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2140           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2141     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2142           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2143     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2144
2145     /* Save away the information */
2146     memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2147
2148     switch (pLight->Type) {
2149     case D3DLIGHT_POINT:
2150         /* Position */
2151         object->lightPosn[0] = pLight->Position.x;
2152         object->lightPosn[1] = pLight->Position.y;
2153         object->lightPosn[2] = pLight->Position.z;
2154         object->lightPosn[3] = 1.0f;
2155         object->cutoff = 180.0f;
2156         /* FIXME: Range */
2157         break;
2158
2159     case D3DLIGHT_DIRECTIONAL:
2160         /* Direction */
2161         object->lightPosn[0] = -pLight->Direction.x;
2162         object->lightPosn[1] = -pLight->Direction.y;
2163         object->lightPosn[2] = -pLight->Direction.z;
2164         object->lightPosn[3] = 0.0;
2165         object->exponent     = 0.0f;
2166         object->cutoff       = 180.0f;
2167         break;
2168
2169     case D3DLIGHT_SPOT:
2170         /* Position */
2171         object->lightPosn[0] = pLight->Position.x;
2172         object->lightPosn[1] = pLight->Position.y;
2173         object->lightPosn[2] = pLight->Position.z;
2174         object->lightPosn[3] = 1.0;
2175
2176         /* Direction */
2177         object->lightDirn[0] = pLight->Direction.x;
2178         object->lightDirn[1] = pLight->Direction.y;
2179         object->lightDirn[2] = pLight->Direction.z;
2180         object->lightDirn[3] = 1.0;
2181
2182         /*
2183          * opengl-ish and d3d-ish spot lights use too different models for the
2184          * light "intensity" as a function of the angle towards the main light direction,
2185          * so we only can approximate very roughly.
2186          * however spot lights are rather rarely used in games (if ever used at all).
2187          * furthermore if still used, probably nobody pays attention to such details.
2188          */
2189         if (pLight->Falloff == 0) {
2190             rho = 6.28f;
2191         } else {
2192             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2193         }
2194         if (rho < 0.0001) rho = 0.0001f;
2195         object->exponent = -0.3/log(cos(rho/2));
2196         object->cutoff = pLight->Phi*90/M_PI;
2197
2198         /* FIXME: Range */
2199         break;
2200
2201     default:
2202         FIXME("Unrecognized light type %d\n", pLight->Type);
2203     }
2204
2205     /* Update the live definitions if the light is currently assigned a glIndex */
2206     if (object->glIndex != -1) {
2207         setup_light(iface, object->glIndex, object);
2208     }
2209     return WINED3D_OK;
2210 }
2211
2212 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2213     PLIGHTINFOEL *lightInfo = NULL;
2214     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2215     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2216
2217     /* Locate the light in the live lights */
2218     lightInfo = This->stateBlock->lights;
2219     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2220
2221     if (lightInfo == NULL) {
2222         TRACE("Light information requested but light not defined\n");
2223         return WINED3DERR_INVALIDCALL;
2224     }
2225
2226     memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2227     return WINED3D_OK;
2228 }
2229
2230 /*****
2231  * Get / Set Light Enable
2232  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2233  *****/
2234 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2235     PLIGHTINFOEL *lightInfo = NULL;
2236     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2237     TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2238
2239     /* If recording state block, just add to end of lights chain with changedEnable set to true */
2240     if (This->isRecordingState) {
2241         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2242         if (NULL == lightInfo) {
2243             return WINED3DERR_OUTOFVIDEOMEMORY;
2244         }
2245         lightInfo->OriginalIndex = Index;
2246         lightInfo->glIndex = -1;
2247         lightInfo->enabledChanged = TRUE;
2248
2249         /* Add to the END of the chain of lights changes to be replayed */
2250         if (This->updateStateBlock->lights == NULL) {
2251             This->updateStateBlock->lights = lightInfo;
2252         } else {
2253             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2254             while (temp->next != NULL) temp=temp->next;
2255             temp->next = lightInfo;
2256         }
2257         TRACE("Recording... not performing anything more\n");
2258         return WINED3D_OK;
2259     }
2260
2261     /* Not recording... So, locate the light in the live lights */
2262     lightInfo = This->stateBlock->lights;
2263     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2264
2265     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2266     if (lightInfo == NULL) {
2267         D3DLIGHT9 lightParms;
2268         /* Warning - untested code :-) Prob safe to change fixme to a trace but
2269              wait until someone confirms it seems to work!                     */
2270         TRACE("Light enabled requested but light not defined, so defining one!\n");
2271         lightParms.Type         = D3DLIGHT_DIRECTIONAL;
2272         lightParms.Diffuse.r    = 1.0;
2273         lightParms.Diffuse.g    = 1.0;
2274         lightParms.Diffuse.b    = 1.0;
2275         lightParms.Diffuse.a    = 0.0;
2276         lightParms.Specular.r   = 0.0;
2277         lightParms.Specular.g   = 0.0;
2278         lightParms.Specular.b   = 0.0;
2279         lightParms.Specular.a   = 0.0;
2280         lightParms.Ambient.r    = 0.0;
2281         lightParms.Ambient.g    = 0.0;
2282         lightParms.Ambient.b    = 0.0;
2283         lightParms.Ambient.a    = 0.0;
2284         lightParms.Position.x   = 0.0;
2285         lightParms.Position.y   = 0.0;
2286         lightParms.Position.z   = 0.0;
2287         lightParms.Direction.x  = 0.0;
2288         lightParms.Direction.y  = 0.0;
2289         lightParms.Direction.z  = 1.0;
2290         lightParms.Range        = 0.0;
2291         lightParms.Falloff      = 0.0;
2292         lightParms.Attenuation0 = 0.0;
2293         lightParms.Attenuation1 = 0.0;
2294         lightParms.Attenuation2 = 0.0;
2295         lightParms.Theta        = 0.0;
2296         lightParms.Phi          = 0.0;
2297         IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2298
2299         /* Search for it again! Should be fairly quick as near head of list */
2300         lightInfo = This->stateBlock->lights;
2301         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2302         if (lightInfo == NULL) {
2303             FIXME("Adding default lights has failed dismally\n");
2304             return WINED3DERR_INVALIDCALL;
2305         }
2306     }
2307
2308     /* OK, we now have a light... */
2309     if (Enable == FALSE) {
2310
2311         /* If we are disabling it, check it was enabled, and
2312            still only do something if it has assigned a glIndex (which it should have!)   */
2313         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2314             TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2315             ENTER_GL();
2316             glDisable(GL_LIGHT0 + lightInfo->glIndex);
2317             checkGLcall("glDisable GL_LIGHT0+Index");
2318             LEAVE_GL();
2319         } else {
2320             TRACE("Nothing to do as light was not enabled\n");
2321         }
2322         lightInfo->lightEnabled = FALSE;
2323     } else {
2324
2325         /* We are enabling it. If it is enabled, it's really simple */
2326         if (lightInfo->lightEnabled) {
2327             /* nop */
2328             TRACE("Nothing to do as light was enabled\n");
2329
2330         /* If it already has a glIndex, it's still simple */
2331         } else if (lightInfo->glIndex != -1) {
2332             TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2333             lightInfo->lightEnabled = TRUE;
2334             ENTER_GL();
2335             glEnable(GL_LIGHT0 + lightInfo->glIndex);
2336             checkGLcall("glEnable GL_LIGHT0+Index already setup");
2337             LEAVE_GL();
2338
2339         /* Otherwise got to find space - lights are ordered gl indexes first */
2340         } else {
2341             PLIGHTINFOEL *bsf  = NULL;
2342             PLIGHTINFOEL *pos  = This->stateBlock->lights;
2343             PLIGHTINFOEL *prev = NULL;
2344             int           Index= 0;
2345             int           glIndex = -1;
2346
2347             /* Try to minimize changes as much as possible */
2348             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2349
2350                 /* Try to remember which index can be replaced if necessary */
2351                 if (bsf==NULL && pos->lightEnabled == FALSE) {
2352                     /* Found a light we can replace, save as best replacement */
2353                     bsf = pos;
2354                 }
2355
2356                 /* Step to next space */
2357                 prev = pos;
2358                 pos = pos->next;
2359                 Index ++;
2360             }
2361
2362             /* If we have too many active lights, fail the call */
2363             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2364                 FIXME("Program requests too many concurrent lights\n");
2365                 return WINED3DERR_INVALIDCALL;
2366
2367             /* If we have allocated all lights, but not all are enabled,
2368                reuse one which is not enabled                           */
2369             } else if (Index == This->maxConcurrentLights) {
2370                 /* use bsf - Simply swap the new light and the BSF one */
2371                 PLIGHTINFOEL *bsfNext = bsf->next;
2372                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2373
2374                 /* Sort out ends */
2375                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2376                 if (bsf->prev != NULL) {
2377                     bsf->prev->next = lightInfo;
2378                 } else {
2379                     This->stateBlock->lights = lightInfo;
2380                 }
2381
2382                 /* If not side by side, lots of chains to update */
2383                 if (bsf->next != lightInfo) {
2384                     lightInfo->prev->next = bsf;
2385                     bsf->next->prev = lightInfo;
2386                     bsf->next       = lightInfo->next;
2387                     bsf->prev       = lightInfo->prev;
2388                     lightInfo->next = bsfNext;
2389                     lightInfo->prev = bsfPrev;
2390
2391                 } else {
2392                     /* Simple swaps */
2393                     bsf->prev = lightInfo;
2394                     bsf->next = lightInfo->next;
2395                     lightInfo->next = bsf;
2396                     lightInfo->prev = bsfPrev;
2397                 }
2398
2399
2400                 /* Update states */
2401                 glIndex = bsf->glIndex;
2402                 bsf->glIndex = -1;
2403                 lightInfo->glIndex = glIndex;
2404                 lightInfo->lightEnabled = TRUE;
2405
2406                 /* Finally set up the light in gl itself */
2407                 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2408                 ENTER_GL();
2409                 setup_light(iface, glIndex, lightInfo);
2410                 glEnable(GL_LIGHT0 + glIndex);
2411                 checkGLcall("glEnable GL_LIGHT0 new setup");
2412                 LEAVE_GL();
2413
2414             /* If we reached the end of the allocated lights, with space in the
2415                gl lights, setup a new light                                     */
2416             } else if (pos->glIndex == -1) {
2417
2418                 /* We reached the end of the allocated gl lights, so already
2419                     know the index of the next one!                          */
2420                 glIndex = Index;
2421                 lightInfo->glIndex = glIndex;
2422                 lightInfo->lightEnabled = TRUE;
2423
2424                 /* In an ideal world, it's already in the right place */
2425                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2426                    /* No need to move it */
2427                 } else {
2428                     /* Remove this light from the list */
2429                     lightInfo->prev->next = lightInfo->next;
2430                     if (lightInfo->next != NULL) {
2431                         lightInfo->next->prev = lightInfo->prev;
2432                     }
2433
2434                     /* Add in at appropriate place (inbetween prev and pos) */
2435                     lightInfo->prev = prev;
2436                     lightInfo->next = pos;
2437                     if (prev == NULL) {
2438                         This->stateBlock->lights = lightInfo;
2439                     } else {
2440                         prev->next = lightInfo;
2441                     }
2442                     if (pos != NULL) {
2443                         pos->prev = lightInfo;
2444                     }
2445                 }
2446
2447                 /* Finally set up the light in gl itself */
2448                 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2449                 ENTER_GL();
2450                 setup_light(iface, glIndex, lightInfo);
2451                 glEnable(GL_LIGHT0 + glIndex);
2452                 checkGLcall("glEnable GL_LIGHT0 new setup");
2453                 LEAVE_GL();
2454
2455             }
2456         }
2457     }
2458     return WINED3D_OK;
2459 }
2460
2461 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2462
2463     PLIGHTINFOEL *lightInfo = NULL;
2464     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2465     TRACE("(%p) : for idx(%ld)\n", This, Index);
2466
2467     /* Locate the light in the live lights */
2468     lightInfo = This->stateBlock->lights;
2469     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2470
2471     if (lightInfo == NULL) {
2472         TRACE("Light enabled state requested but light not defined\n");
2473         return WINED3DERR_INVALIDCALL;
2474     }
2475     *pEnable = lightInfo->lightEnabled;
2476     return WINED3D_OK;
2477 }
2478
2479 /*****
2480  * Get / Set Clip Planes
2481  *****/
2482 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2483     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2484     TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2485
2486     /* Validate Index */
2487     if (Index >= GL_LIMITS(clipplanes)) {
2488         TRACE("Application has requested clipplane this device doesn't support\n");
2489         return WINED3DERR_INVALIDCALL;
2490     }
2491
2492     This->updateStateBlock->changed.clipplane[Index] = TRUE;
2493     This->updateStateBlock->set.clipplane[Index] = TRUE;
2494     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2495     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2496     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2497     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2498
2499     /* Handle recording of state blocks */
2500     if (This->isRecordingState) {
2501         TRACE("Recording... not performing anything\n");
2502         return WINED3D_OK;
2503     }
2504
2505     /* Apply it */
2506
2507     ENTER_GL();
2508
2509     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2510     glMatrixMode(GL_MODELVIEW);
2511     glPushMatrix();
2512     glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2513
2514     TRACE("Clipplane [%f,%f,%f,%f]\n",
2515           This->updateStateBlock->clipplane[Index][0],
2516           This->updateStateBlock->clipplane[Index][1],
2517           This->updateStateBlock->clipplane[Index][2],
2518           This->updateStateBlock->clipplane[Index][3]);
2519     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2520     checkGLcall("glClipPlane");
2521
2522     glPopMatrix();
2523     LEAVE_GL();
2524
2525     return WINED3D_OK;
2526 }
2527
2528 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2529     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2530     TRACE("(%p) : for idx %ld\n", This, Index);
2531
2532     /* Validate Index */
2533     if (Index >= GL_LIMITS(clipplanes)) {
2534         TRACE("Application has requested clipplane this device doesn't support\n");
2535         return WINED3DERR_INVALIDCALL;
2536     }
2537
2538     pPlane[0] = This->stateBlock->clipplane[Index][0];
2539     pPlane[1] = This->stateBlock->clipplane[Index][1];
2540     pPlane[2] = This->stateBlock->clipplane[Index][2];
2541     pPlane[3] = This->stateBlock->clipplane[Index][3];
2542     return WINED3D_OK;
2543 }
2544
2545 /*****
2546  * Get / Set Clip Plane Status
2547  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2548  *****/
2549 HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2550     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2551     FIXME("(%p) : stub\n", This);
2552     if (NULL == pClipStatus) {
2553       return WINED3DERR_INVALIDCALL;
2554     }
2555     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2556     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2557     return WINED3D_OK;
2558 }
2559
2560 HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2561     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2562     FIXME("(%p) : stub\n", This);
2563     if (NULL == pClipStatus) {
2564       return WINED3DERR_INVALIDCALL;
2565     }
2566     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2567     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2568     return WINED3D_OK;
2569 }
2570
2571 /*****
2572  * Get / Set Material
2573  *   WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2574  *****/
2575 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2576     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2577
2578     This->updateStateBlock->changed.material = TRUE;
2579     This->updateStateBlock->set.material = TRUE;
2580     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2581
2582     /* Handle recording of state blocks */
2583     if (This->isRecordingState) {
2584         TRACE("Recording... not performing anything\n");
2585         return WINED3D_OK;
2586     }
2587
2588     ENTER_GL();
2589     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2590         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2591     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2592         pMaterial->Ambient.b, pMaterial->Ambient.a);
2593     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2594         pMaterial->Specular.b, pMaterial->Specular.a);
2595     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2596         pMaterial->Emissive.b, pMaterial->Emissive.a);
2597     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2598
2599     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2600     checkGLcall("glMaterialfv(GL_AMBIENT)");
2601     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2602     checkGLcall("glMaterialfv(GL_DIFFUSE)");
2603
2604     /* Only change material color if specular is enabled, otherwise it is set to black */
2605     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2606        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2607        checkGLcall("glMaterialfv(GL_SPECULAR");
2608     } else {
2609        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2610        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2611        checkGLcall("glMaterialfv(GL_SPECULAR");
2612     }
2613     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2614     checkGLcall("glMaterialfv(GL_EMISSION)");
2615     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2616     checkGLcall("glMaterialf(GL_SHININESS");
2617
2618     LEAVE_GL();
2619     return WINED3D_OK;
2620 }
2621
2622 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2623     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2624     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2625     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2626         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2627     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2628         pMaterial->Ambient.b, pMaterial->Ambient.a);
2629     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2630         pMaterial->Specular.b, pMaterial->Specular.a);
2631     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2632         pMaterial->Emissive.b, pMaterial->Emissive.a);
2633     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2634
2635     return WINED3D_OK;
2636 }
2637
2638 /*****
2639  * Get / Set Indices
2640  *****/
2641 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2642                                              UINT BaseVertexIndex) {
2643     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
2644     IWineD3DIndexBuffer *oldIdxs;
2645
2646     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2647     oldIdxs = This->updateStateBlock->pIndexData;
2648
2649     This->updateStateBlock->changed.indices = TRUE;
2650     This->updateStateBlock->set.indices = TRUE;
2651     This->updateStateBlock->pIndexData = pIndexData;
2652     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2653
2654     /* Handle recording of state blocks */
2655     if (This->isRecordingState) {
2656         TRACE("Recording... not performing anything\n");
2657         return WINED3D_OK;
2658     }
2659
2660     if (NULL != pIndexData) {
2661         IWineD3DIndexBuffer_AddRef(pIndexData);
2662     }
2663     if (NULL != oldIdxs) {
2664         IWineD3DIndexBuffer_Release(oldIdxs);
2665     }
2666     return WINED3D_OK;
2667 }
2668
2669 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2670     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2671
2672     *ppIndexData = This->stateBlock->pIndexData;
2673
2674     /* up ref count on ppindexdata */
2675     if (*ppIndexData) {
2676         IWineD3DIndexBuffer_AddRef(*ppIndexData);
2677         *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2678         TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2679     }else{
2680         TRACE("(%p) No index data set\n", This);
2681     }
2682     TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2683
2684     return WINED3D_OK;
2685 }
2686
2687 /*****
2688  * Get / Set Viewports
2689  *****/
2690 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2691     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2692
2693     TRACE("(%p)\n", This);
2694     This->updateStateBlock->changed.viewport = TRUE;
2695     This->updateStateBlock->set.viewport = TRUE;
2696     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2697
2698     /* Handle recording of state blocks */
2699     if (This->isRecordingState) {
2700         TRACE("Recording... not performing anything\n");
2701         return WINED3D_OK;
2702     }
2703     This->viewport_changed = TRUE;
2704
2705     ENTER_GL();
2706
2707     TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2708           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2709
2710     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2711     checkGLcall("glDepthRange");
2712     /* Note: GL requires lower left, DirectX supplies upper left */
2713     /* TODO: replace usage of renderTarget with context management */
2714     glViewport(pViewport->X,
2715                (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2716                pViewport->Width, pViewport->Height);
2717
2718     checkGLcall("glViewport");
2719
2720     LEAVE_GL();
2721
2722     return WINED3D_OK;
2723
2724 }
2725
2726 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2727     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2728     TRACE("(%p)\n", This);
2729     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2730     return WINED3D_OK;
2731 }
2732
2733 /*****
2734  * Get / Set Render States
2735  * TODO: Verify against dx9 definitions
2736  *****/
2737 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2738
2739     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
2740     DWORD                OldValue = This->stateBlock->renderState[State];
2741
2742     /* Simple way of referring to either a DWORD or a 4 byte float */
2743     union {
2744         DWORD d;
2745         float f;
2746     } tmpvalue;
2747
2748     TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2749     This->updateStateBlock->changed.renderState[State] = TRUE;
2750     This->updateStateBlock->set.renderState[State] = TRUE;
2751     This->updateStateBlock->renderState[State] = Value;
2752
2753     /* Handle recording of state blocks */
2754     if (This->isRecordingState) {
2755         TRACE("Recording... not performing anything\n");
2756         return WINED3D_OK;
2757     }
2758
2759     ENTER_GL();
2760
2761     switch (State) {
2762     case WINED3DRS_FILLMODE                  :
2763         switch ((D3DFILLMODE) Value) {
2764         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2765         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2766         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2767         default:
2768             FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2769         }
2770         checkGLcall("glPolygonMode (fillmode)");
2771         break;
2772
2773     case WINED3DRS_LIGHTING                  :
2774         if (Value) {
2775             glEnable(GL_LIGHTING);
2776             checkGLcall("glEnable GL_LIGHTING");
2777         } else {
2778             glDisable(GL_LIGHTING);
2779             checkGLcall("glDisable GL_LIGHTING");
2780         }
2781         break;
2782
2783     case WINED3DRS_ZENABLE                   :
2784         switch ((D3DZBUFFERTYPE) Value) {
2785         case D3DZB_FALSE:
2786             glDisable(GL_DEPTH_TEST);
2787             checkGLcall("glDisable GL_DEPTH_TEST");
2788             break;
2789         case D3DZB_TRUE:
2790             glEnable(GL_DEPTH_TEST);
2791             checkGLcall("glEnable GL_DEPTH_TEST");
2792             break;
2793         case D3DZB_USEW:
2794             glEnable(GL_DEPTH_TEST);
2795             checkGLcall("glEnable GL_DEPTH_TEST");
2796             FIXME("W buffer is not well handled\n");
2797             break;
2798         default:
2799             FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2800         }
2801         break;
2802
2803     case WINED3DRS_CULLMODE                  :
2804
2805         /* If we are culling "back faces with clockwise vertices" then
2806            set front faces to be counter clockwise and enable culling
2807            of back faces                                               */
2808         switch ((D3DCULL) Value) {
2809         case D3DCULL_NONE:
2810             glDisable(GL_CULL_FACE);
2811             checkGLcall("glDisable GL_CULL_FACE");
2812             break;
2813         case D3DCULL_CW:
2814             glEnable(GL_CULL_FACE);
2815             checkGLcall("glEnable GL_CULL_FACE");
2816             if (This->renderUpsideDown) {
2817                 glFrontFace(GL_CW);
2818                 checkGLcall("glFrontFace GL_CW");
2819             } else {
2820                 glFrontFace(GL_CCW);
2821                 checkGLcall("glFrontFace GL_CCW");
2822             }
2823             glCullFace(GL_BACK);
2824             break;
2825         case D3DCULL_CCW:
2826             glEnable(GL_CULL_FACE);
2827             checkGLcall("glEnable GL_CULL_FACE");
2828             if (This->renderUpsideDown) {
2829                 glFrontFace(GL_CCW);
2830                 checkGLcall("glFrontFace GL_CCW");
2831             } else {
2832                 glFrontFace(GL_CW);
2833                 checkGLcall("glFrontFace GL_CW");
2834             }
2835             glCullFace(GL_BACK);
2836             break;
2837         default:
2838             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2839         }
2840         break;
2841
2842     case WINED3DRS_SHADEMODE                 :
2843         switch ((D3DSHADEMODE) Value) {
2844         case D3DSHADE_FLAT:
2845             glShadeModel(GL_FLAT);
2846             checkGLcall("glShadeModel");
2847             break;
2848         case D3DSHADE_GOURAUD:
2849             glShadeModel(GL_SMOOTH);
2850             checkGLcall("glShadeModel");
2851             break;
2852         case D3DSHADE_PHONG:
2853             FIXME("D3DSHADE_PHONG isn't supported?\n");
2854
2855             LEAVE_GL();
2856             return WINED3DERR_INVALIDCALL;
2857         default:
2858             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2859         }
2860         break;
2861
2862     case WINED3DRS_DITHERENABLE              :
2863         if (Value) {
2864             glEnable(GL_DITHER);
2865             checkGLcall("glEnable GL_DITHER");
2866         } else {
2867             glDisable(GL_DITHER);
2868             checkGLcall("glDisable GL_DITHER");
2869         }
2870         break;
2871
2872     case WINED3DRS_ZWRITEENABLE              :
2873         if (Value) {
2874             glDepthMask(1);
2875             checkGLcall("glDepthMask");
2876         } else {
2877             glDepthMask(0);
2878             checkGLcall("glDepthMask");
2879         }
2880         break;
2881
2882     case WINED3DRS_ZFUNC                     :
2883         {
2884             int glParm = GL_LESS;
2885
2886             switch ((D3DCMPFUNC) Value) {
2887             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2888             case D3DCMP_LESS:          glParm=GL_LESS; break;
2889             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2890             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2891             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2892             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2893             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2894             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2895             default:
2896                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2897             }
2898             glDepthFunc(glParm);
2899             checkGLcall("glDepthFunc");
2900         }
2901         break;
2902
2903     case WINED3DRS_AMBIENT                   :
2904         {
2905             float col[4];
2906             D3DCOLORTOGLFLOAT4(Value, col);
2907             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2908             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2909             checkGLcall("glLightModel for MODEL_AMBIENT");
2910
2911         }
2912         break;
2913
2914     case WINED3DRS_ALPHABLENDENABLE          :
2915         if (Value) {
2916             glEnable(GL_BLEND);
2917             checkGLcall("glEnable GL_BLEND");
2918         } else {
2919             glDisable(GL_BLEND);
2920             checkGLcall("glDisable GL_BLEND");
2921         };
2922         break;
2923
2924     case WINED3DRS_SRCBLEND                  :
2925     case WINED3DRS_DESTBLEND                 :
2926         {
2927             int newVal = GL_ZERO;
2928             switch (Value) {
2929             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
2930             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
2931             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
2932             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
2933             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
2934             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
2935             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
2936             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
2937             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
2938             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
2939             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
2940
2941             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
2942                 This->srcBlend = newVal;
2943                 This->dstBlend = newVal;
2944                 break;
2945
2946             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
2947                 This->srcBlend = newVal;
2948                 This->dstBlend = newVal;
2949                 break;
2950             default:
2951                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2952             }
2953
2954             if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2955             if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2956             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2957             glBlendFunc(This->srcBlend, This->dstBlend);
2958
2959             checkGLcall("glBlendFunc");
2960         }
2961         break;
2962
2963     case WINED3DRS_ALPHATESTENABLE           :
2964         if (Value) {
2965             glEnable(GL_ALPHA_TEST);
2966             checkGLcall("glEnable GL_ALPHA_TEST");
2967         } else {
2968             glDisable(GL_ALPHA_TEST);
2969             checkGLcall("glDisable GL_ALPHA_TEST");
2970         }
2971         break;
2972
2973     case WINED3DRS_ALPHAFUNC                 :
2974         {
2975             int glParm = GL_LESS;
2976             float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2977
2978             switch ((D3DCMPFUNC) Value) {
2979             case D3DCMP_NEVER:         glParm = GL_NEVER; break;
2980             case D3DCMP_LESS:          glParm = GL_LESS; break;
2981             case D3DCMP_EQUAL:         glParm = GL_EQUAL; break;
2982             case D3DCMP_LESSEQUAL:     glParm = GL_LEQUAL; break;
2983             case D3DCMP_GREATER:       glParm = GL_GREATER; break;
2984             case D3DCMP_NOTEQUAL:      glParm = GL_NOTEQUAL; break;
2985             case D3DCMP_GREATEREQUAL:  glParm = GL_GEQUAL; break;
2986             case D3DCMP_ALWAYS:        glParm = GL_ALWAYS; break;
2987             default:
2988                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2989             }
2990             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2991             glAlphaFunc(glParm, ref);
2992             This->alphafunc = glParm;
2993             checkGLcall("glAlphaFunc");
2994         }
2995         break;
2996
2997     case WINED3DRS_ALPHAREF                  :
2998         {
2999             int glParm = This->alphafunc;
3000             float ref = 1.0f;
3001
3002             ref = ((float) Value) / 255.0f;
3003             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
3004             glAlphaFunc(glParm, ref);
3005             checkGLcall("glAlphaFunc");
3006         }
3007         break;
3008
3009     case WINED3DRS_CLIPPLANEENABLE           :
3010     case WINED3DRS_CLIPPING                  :
3011         {
3012             /* Ensure we only do the changed clip planes */
3013             DWORD enable  = 0xFFFFFFFF;
3014             DWORD disable = 0x00000000;
3015
3016             /* If enabling / disabling all */
3017             if (State == WINED3DRS_CLIPPING) {
3018                 if (Value) {
3019                     enable  = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3020                     disable = 0x00;
3021                 } else {
3022                     disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3023                     enable  = 0x00;
3024                 }
3025             } else {
3026                 enable =   Value & ~OldValue;
3027                 disable = ~Value &  OldValue;
3028             }
3029
3030             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
3031             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
3032             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
3033             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
3034             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
3035             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
3036
3037             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3038             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3039             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3040             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3041             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3042             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3043
3044             /** update clipping status */
3045             if (enable) {
3046               This->stateBlock->clip_status.ClipUnion = 0;
3047               This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3048             } else {
3049               This->stateBlock->clip_status.ClipUnion = 0;
3050               This->stateBlock->clip_status.ClipIntersection = 0;
3051             }
3052         }
3053         break;
3054
3055     case WINED3DRS_BLENDOP                   :
3056         {
3057             int glParm = GL_FUNC_ADD;
3058
3059             switch ((D3DBLENDOP) Value) {
3060             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
3061             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
3062             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3063             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
3064             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
3065             default:
3066                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3067             }
3068             TRACE("glBlendEquation(%x)\n", glParm);
3069             glBlendEquation(glParm);
3070             checkGLcall("glBlendEquation");
3071         }
3072         break;
3073
3074     case WINED3DRS_TEXTUREFACTOR             :
3075         {
3076             unsigned int i;
3077
3078             /* Note the texture color applies to all textures whereas
3079                GL_TEXTURE_ENV_COLOR applies to active only */
3080             float col[4];
3081             D3DCOLORTOGLFLOAT4(Value, col);
3082             /* Set the default alpha blend color */
3083             glBlendColor(col[0], col[1], col[2], col[3]);
3084             checkGLcall("glBlendColor");
3085
3086             /* And now the default texture color as well */
3087             for (i = 0; i < GL_LIMITS(textures); i++) {
3088
3089                 /* Note the D3DRS value applies to all textures, but GL has one
3090                    per texture, so apply it now ready to be used!               */
3091                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3092                     GLACTIVETEXTURE(i);
3093                 } else if (i>0) {
3094                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3095                 }
3096
3097                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3098                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3099             }
3100         }
3101         break;
3102
3103     case WINED3DRS_SPECULARENABLE            :
3104         {
3105             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3106                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3107                specular color. This is wrong:
3108                Separate specular color means the specular colour is maintained separately, whereas
3109                single color means it is merged in. However in both cases they are being used to
3110                some extent.
3111                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3112                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3113                   running 1.4 yet!
3114              */
3115               if (Value) {
3116                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3117                 checkGLcall("glMaterialfv");
3118                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3119                   glEnable(GL_COLOR_SUM_EXT);
3120                 } else {
3121                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
3122                 }
3123                 checkGLcall("glEnable(GL_COLOR_SUM)");
3124               } else {
3125                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3126
3127                 /* for the case of enabled lighting: */
3128                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3129                 checkGLcall("glMaterialfv");
3130
3131                 /* for the case of disabled lighting: */
3132                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3133                   glDisable(GL_COLOR_SUM_EXT);
3134                 } else {
3135                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
3136                 }
3137                 checkGLcall("glDisable(GL_COLOR_SUM)");
3138               }
3139         }
3140         break;
3141
3142     case WINED3DRS_STENCILENABLE             :
3143         if (Value) {
3144             glEnable(GL_STENCIL_TEST);
3145             checkGLcall("glEnable GL_STENCIL_TEST");
3146         } else {
3147             glDisable(GL_STENCIL_TEST);
3148             checkGLcall("glDisable GL_STENCIL_TEST");
3149         }
3150         break;
3151
3152     case WINED3DRS_STENCILFUNC :
3153     {
3154         GLint func;
3155         GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3156         GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3157
3158         func = GL_ALWAYS;
3159         switch ((D3DCMPFUNC)Value) {
3160             case D3DCMP_NEVER: func = GL_NEVER; break;
3161             case D3DCMP_LESS: func = GL_LESS; break;
3162             case D3DCMP_EQUAL: func = GL_EQUAL; break;
3163             case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3164             case D3DCMP_GREATER: func = GL_GREATER; break;
3165             case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3166             case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3167             case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3168             default:
3169                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3170         }
3171         This->stencilfunc = func;
3172         if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3173 #if 0 /* Don't use OpenGL 2.0 calls for now */
3174             if(GL_EXTCALL(glStencilFuncSeparate)) {
3175                 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
3176                 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3177             }
3178             else
3179 #endif
3180             if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3181                 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3182                 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3183                 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3184                 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3185                 glStencilFunc(func, ref, mask);
3186                 checkGLcall("glStencilFunc(...)");
3187             }
3188             else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3189                 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT, func, ref, mask));
3190                 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3191             } else {
3192                 TRACE("Separate stencil function not supported on this version of opengl");
3193                 glStencilFunc(func, ref, mask);
3194                 checkGLcall("glStencilFunc(...)");
3195             }
3196         } else {
3197             glStencilFunc(func, ref, mask);
3198             checkGLcall("glStencilFunc(...)");
3199         }
3200         break;
3201     }
3202     case WINED3DRS_STENCILREF                :
3203         {
3204            int glParm = This->stencilfunc;
3205            int ref = 0;
3206            GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3207
3208            ref = Value;
3209            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3210            glStencilFunc(glParm, ref, mask);
3211            checkGLcall("glStencilFunc");
3212         }
3213         break;
3214
3215     case WINED3DRS_STENCILMASK               :
3216         {
3217            int glParm = This->stencilfunc;
3218            int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3219            GLuint mask = Value;
3220
3221            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3222            glStencilFunc(glParm, ref, mask);
3223            checkGLcall("glStencilFunc");
3224         }
3225         break;
3226
3227     case WINED3DRS_STENCILFAIL               :
3228     case WINED3DRS_STENCILZFAIL              :
3229     case WINED3DRS_STENCILPASS               :
3230     {
3231         GLint stencilFail;
3232         GLint depthFail;
3233         GLint stencilPass;
3234
3235         GLint action = StencilOp(Value);
3236
3237         glGetIntegerv(GL_STENCIL_FAIL, &stencilFail);
3238         glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &depthFail);
3239         glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &stencilPass);
3240
3241         if(WINED3DRS_STENCILFAIL == State) {
3242             stencilFail = action;
3243         }
3244         else if(WINED3DRS_STENCILZFAIL == State) {
3245             depthFail = action;
3246         }
3247         else if(WINED3DRS_STENCILPASS == State) {
3248             stencilPass = action;
3249         }
3250
3251         if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3252 #if 0 /* Don't use OpenGL 2.0 calls for now */
3253             if(GL_EXTCALL(glStencilOpSeparate)) {
3254                 GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
3255                 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3256             }
3257             else
3258 #endif
3259             if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3260                 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3261                 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3262                 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
3263                 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3264                 glStencilOp(stencilFail, depthFail, stencilPass);
3265                 checkGLcall("glStencilOp(...)");
3266             }
3267             else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3268                 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
3269                 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3270             } else {
3271                 TRACE("Separate stencil operation not supported on this version of opengl");
3272                 glStencilOp(stencilFail, depthFail, stencilPass);
3273                 checkGLcall("glStencilOp(...)");
3274             }
3275         } else {
3276             glStencilOp(stencilFail, depthFail, stencilPass);
3277             checkGLcall("glStencilOp(...)");
3278         }
3279         break;
3280     }
3281     case WINED3DRS_STENCILWRITEMASK          :
3282         {
3283             glStencilMask(Value);
3284             TRACE("glStencilMask(%lu)\n", Value);
3285             checkGLcall("glStencilMask");
3286         }
3287         break;
3288
3289     case WINED3DRS_FOGENABLE                 :
3290         {
3291           if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3292                glEnable(GL_FOG);
3293                checkGLcall("glEnable GL_FOG");
3294             } else {
3295                glDisable(GL_FOG);
3296                checkGLcall("glDisable GL_FOG");
3297             }
3298         }
3299         break;
3300
3301     case WINED3DRS_RANGEFOGENABLE            :
3302         {
3303             if (Value) {
3304               TRACE("Enabled RANGEFOG");
3305             } else {
3306               TRACE("Disabled RANGEFOG");
3307             }
3308         }
3309         break;
3310
3311     case WINED3DRS_FOGCOLOR                  :
3312         {
3313             float col[4];
3314             D3DCOLORTOGLFLOAT4(Value, col);
3315             /* Set the default alpha blend color */
3316             glFogfv(GL_FOG_COLOR, &col[0]);
3317             checkGLcall("glFog GL_FOG_COLOR");
3318         }
3319         break;
3320
3321     case WINED3DRS_FOGTABLEMODE              :
3322         {
3323           glHint(GL_FOG_HINT, GL_NICEST);
3324           switch (Value) {
3325           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3326           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3327           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3328           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3329           default:
3330             FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3331           }
3332           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3333             glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3334           }
3335         }
3336         break;
3337
3338     case WINED3DRS_FOGVERTEXMODE             :
3339         {
3340           glHint(GL_FOG_HINT, GL_FASTEST);
3341           switch (Value) {
3342           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3343           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3344           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3345           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3346           default:
3347             FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3348           }
3349           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3350             glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3351           }
3352         }
3353         break;
3354
3355     case WINED3DRS_FOGSTART                  :
3356         {
3357             tmpvalue.d = Value;
3358             glFogfv(GL_FOG_START, &tmpvalue.f);
3359             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3360             TRACE("Fog Start == %f\n", tmpvalue.f);
3361         }
3362         break;
3363
3364     case WINED3DRS_FOGEND                    :
3365         {
3366             tmpvalue.d = Value;
3367             glFogfv(GL_FOG_END, &tmpvalue.f);
3368             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3369             TRACE("Fog End == %f\n", tmpvalue.f);
3370         }
3371         break;
3372
3373     case WINED3DRS_FOGDENSITY                :
3374         {
3375             tmpvalue.d = Value;
3376             glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3377             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3378         }
3379         break;
3380
3381     case WINED3DRS_VERTEXBLEND               :
3382         {
3383           This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3384           TRACE("Vertex Blending state to %ld\n",  Value);
3385         }
3386         break;
3387
3388     case WINED3DRS_TWEENFACTOR               :
3389         {
3390           tmpvalue.d = Value;
3391           This->updateStateBlock->tween_factor = tmpvalue.f;
3392           TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3393         }
3394         break;
3395
3396     case WINED3DRS_INDEXEDVERTEXBLENDENABLE  :
3397         {
3398           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3399         }
3400         break;
3401
3402     case WINED3DRS_COLORVERTEX               :
3403     case WINED3DRS_DIFFUSEMATERIALSOURCE     :
3404     case WINED3DRS_SPECULARMATERIALSOURCE    :
3405     case WINED3DRS_AMBIENTMATERIALSOURCE     :
3406     case WINED3DRS_EMISSIVEMATERIALSOURCE    :
3407         {
3408             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3409
3410             if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3411                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3412                       This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3413                       This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3414                       This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3415                       This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3416
3417                 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3418                     if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3419                         Parm = GL_AMBIENT_AND_DIFFUSE;
3420                     } else {
3421                         Parm = GL_DIFFUSE;
3422                     }
3423                 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3424                     Parm = GL_AMBIENT;
3425                 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3426                     Parm = GL_EMISSION;
3427                 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3428                     Parm = GL_SPECULAR;
3429                 } else {
3430                     Parm = -1;
3431                 }
3432
3433                 if (Parm == -1) {
3434                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3435                 } else {
3436                     This->tracking_color = NEEDS_TRACKING;
3437                     This->tracking_parm  = Parm;
3438                 }
3439
3440             } else {
3441                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3442             }
3443         }
3444         break;
3445
3446     case WINED3DRS_LINEPATTERN               :
3447         {
3448             union {
3449                 DWORD                 d;
3450                 D3DLINEPATTERN        lp;
3451             } tmppattern;
3452             tmppattern.d = Value;
3453
3454             TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3455
3456             if (tmppattern.lp.wRepeatFactor) {
3457                 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3458                 checkGLcall("glLineStipple(repeat, linepattern)");
3459                 glEnable(GL_LINE_STIPPLE);
3460                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3461             } else {
3462                 glDisable(GL_LINE_STIPPLE);
3463                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3464             }
3465         }
3466         break;
3467
3468     case WINED3DRS_ZBIAS                     : /* D3D8 only */
3469         {
3470             if (Value) {
3471                 tmpvalue.d = Value;
3472                 TRACE("ZBias value %f\n", tmpvalue.f);
3473                 glPolygonOffset(0, -tmpvalue.f);
3474                 checkGLcall("glPolygonOffset(0, -Value)");
3475                 glEnable(GL_POLYGON_OFFSET_FILL);
3476                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3477                 glEnable(GL_POLYGON_OFFSET_LINE);
3478                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3479                 glEnable(GL_POLYGON_OFFSET_POINT);
3480                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3481             } else {
3482                 glDisable(GL_POLYGON_OFFSET_FILL);
3483                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3484                 glDisable(GL_POLYGON_OFFSET_LINE);
3485                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3486                 glDisable(GL_POLYGON_OFFSET_POINT);
3487                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3488             }
3489         }
3490         break;
3491
3492     case WINED3DRS_NORMALIZENORMALS          :
3493         if (Value) {
3494             glEnable(GL_NORMALIZE);
3495             checkGLcall("glEnable(GL_NORMALIZE);");
3496         } else {
3497             glDisable(GL_NORMALIZE);
3498             checkGLcall("glDisable(GL_NORMALIZE);");
3499         }
3500         break;
3501
3502     case WINED3DRS_POINTSIZE                 :
3503         /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3504         tmpvalue.d = Value;
3505         TRACE("Set point size to %f\n", tmpvalue.f);
3506         glPointSize(tmpvalue.f);
3507         checkGLcall("glPointSize(...);");
3508         break;
3509
3510     case WINED3DRS_POINTSIZE_MIN             :
3511         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3512           tmpvalue.d = Value;
3513           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3514           checkGLcall("glPointParameterfEXT(...);");
3515         } else {
3516           FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3517         }
3518         break;
3519
3520     case WINED3DRS_POINTSIZE_MAX             :
3521         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3522           tmpvalue.d = Value;
3523           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3524           checkGLcall("glPointParameterfEXT(...);");
3525         } else {
3526           FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3527         }
3528         break;
3529
3530     case WINED3DRS_POINTSCALE_A              :
3531     case WINED3DRS_POINTSCALE_B              :
3532     case WINED3DRS_POINTSCALE_C              :
3533     case WINED3DRS_POINTSCALEENABLE          :
3534     {
3535         /*
3536          * POINTSCALEENABLE controls how point size value is treated. If set to
3537          * true, the point size is scaled with respect to height of viewport.
3538          * When set to false point size is in pixels.
3539          *
3540          * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3541          */
3542
3543         /* Default values */
3544         GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3545
3546         /*
3547          * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3548          * This means that OpenGL will clamp really small point sizes to 1.0f.
3549          * To correct for this we need to multiply by the scale factor when sizes
3550          * are less than 1.0f. scale_factor =  1.0f / point_size.
3551          */
3552         GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3553         if(pointSize > 0.0f) {
3554             GLfloat scaleFactor;
3555
3556             if(pointSize < 1.0f) {
3557                 scaleFactor = pointSize * pointSize;
3558             } else {
3559                 scaleFactor = 1.0f;
3560             }
3561
3562             if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3563                 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3564                     (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3565                 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3566                     (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3567                 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3568                     (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3569             }
3570         }
3571
3572         if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3573             GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3574             checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3575         }
3576         else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3577             GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3578             checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3579         } else {
3580             TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3581         }
3582         break;
3583     }
3584     case WINED3DRS_COLORWRITEENABLE          :
3585       {
3586         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3587               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
3588               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3589               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
3590               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3591         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE,
3592                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3593                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
3594                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3595         checkGLcall("glColorMask(...)");
3596       }
3597       break;
3598
3599     case WINED3DRS_LOCALVIEWER               :
3600       {
3601         GLint state = (Value) ? 1 : 0;
3602         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3603         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3604       }
3605       break;
3606
3607     case WINED3DRS_LASTPIXEL                 :
3608       {
3609         if (Value) {
3610           TRACE("Last Pixel Drawing Enabled\n");
3611         } else {
3612           FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3613         }
3614       }
3615       break;
3616
3617     case WINED3DRS_SOFTWAREVERTEXPROCESSING  :
3618       {
3619         if (Value) {
3620           TRACE("Software Processing Enabled\n");
3621         } else {
3622           TRACE("Software Processing Disabled\n");
3623         }
3624       }
3625       break;
3626
3627       /** not supported */
3628     case WINED3DRS_ZVISIBLE                  :
3629       {
3630         LEAVE_GL();
3631         return WINED3DERR_INVALIDCALL;
3632       }
3633     case WINED3DRS_POINTSPRITEENABLE         :
3634     {
3635         /* TODO: NV_POINT_SPRITE */
3636         if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3637             TRACE("Point sprites not supported\n");
3638             break;
3639         }
3640
3641         /*
3642          * Point sprites are always enabled. Value controls texture coordinate
3643          * replacement mode. Must be set true for point sprites to use
3644          * textures.
3645          */
3646         glEnable(GL_POINT_SPRITE_ARB);
3647         checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3648
3649         if (Value) {
3650             glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3651             checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3652         } else {
3653             glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3654             checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3655         }
3656         break;
3657     }
3658     case WINED3DRS_EDGEANTIALIAS             :
3659     {
3660         if(Value) {
3661             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3662             glEnable(GL_BLEND);
3663             checkGLcall("glEnable(GL_BLEND)");
3664             glEnable(GL_LINE_SMOOTH);
3665             checkGLcall("glEnable(GL_LINE_SMOOTH)");
3666         } else {
3667             glDisable(GL_BLEND);
3668             checkGLcall("glDisable(GL_BLEND)");
3669             glDisable(GL_LINE_SMOOTH);
3670             checkGLcall("glDisable(GL_LINE_SMOOTH)");
3671         }
3672         break;
3673     }
3674     case WINED3DRS_WRAP0                     :
3675     case WINED3DRS_WRAP1                     :
3676     case WINED3DRS_WRAP2                     :
3677     case WINED3DRS_WRAP3                     :
3678     case WINED3DRS_WRAP4                     :
3679     case WINED3DRS_WRAP5                     :
3680     case WINED3DRS_WRAP6                     :
3681     case WINED3DRS_WRAP7                     :
3682     case WINED3DRS_WRAP8                     :
3683     case WINED3DRS_WRAP9                     :
3684     case WINED3DRS_WRAP10                    :
3685     case WINED3DRS_WRAP11                    :
3686     case WINED3DRS_WRAP12                    :
3687     case WINED3DRS_WRAP13                    :
3688     case WINED3DRS_WRAP14                    :
3689     case WINED3DRS_WRAP15                    :
3690     /**
3691     http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3692     http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3693     http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3694     Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3695     http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3696
3697     so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3698     */
3699         TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
3700     break;
3701     case WINED3DRS_MULTISAMPLEANTIALIAS      :
3702     {
3703         if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3704             TRACE("Multisample antialiasing not supported\n");
3705             break;
3706         }
3707
3708         if(Value) {
3709             glEnable(GL_MULTISAMPLE_ARB);
3710             checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3711         } else {
3712             glDisable(GL_MULTISAMPLE_ARB);
3713             checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3714         }
3715         break;
3716     }
3717     case WINED3DRS_SCISSORTESTENABLE :
3718     {
3719         if(Value) {
3720             glEnable(GL_SCISSOR_TEST);
3721             checkGLcall("glEnable(GL_SCISSOR_TEST)");
3722         } else {
3723             glDisable(GL_SCISSOR_TEST);
3724             checkGLcall("glDisable(GL_SCISSOR_TEST)");
3725         }
3726         break;
3727     }
3728     case WINED3DRS_SLOPESCALEDEPTHBIAS :
3729     {
3730         if(Value) {
3731             tmpvalue.d = Value;
3732             glEnable(GL_POLYGON_OFFSET_FILL);
3733             checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3734             glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
3735             checkGLcall("glPolygonOffset(...)");
3736         } else {
3737             glDisable(GL_POLYGON_OFFSET_FILL);
3738             checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3739         }
3740         break;
3741     }
3742     case WINED3DRS_ANTIALIASEDLINEENABLE :
3743     {
3744         if(Value) {
3745             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3746             glEnable(GL_BLEND);
3747             checkGLcall("glEnable(GL_BLEND)");
3748             glEnable(GL_LINE_SMOOTH);
3749             checkGLcall("glEnable(GL_LINE_SMOOTH)");
3750         } else {
3751             glDisable(GL_BLEND);
3752             checkGLcall("glDisable(GL_BLEND)");
3753             glDisable(GL_LINE_SMOOTH);
3754             checkGLcall("glDisable(GL_LINE_SMOOTH)");
3755         }
3756         break;
3757     }
3758     case WINED3DRS_TWOSIDEDSTENCILMODE :
3759     {
3760         if(Value) {
3761             TRACE("Two-sided stencil mode enabled\n");
3762         } else {
3763             TRACE("Two-sided stencil mode disabled\n");
3764         }
3765         break;
3766     }
3767     case WINED3DRS_CCW_STENCILFAIL :
3768     case WINED3DRS_CCW_STENCILZFAIL :
3769     case WINED3DRS_CCW_STENCILPASS :
3770     {
3771         GLint stencilFail;
3772         GLint depthFail;
3773         GLint stencilPass;
3774
3775         GLint action = StencilOp(Value);
3776
3777         glGetIntegerv(GL_STENCIL_BACK_FAIL, &stencilFail);
3778         glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &depthFail);
3779         glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &stencilPass);
3780
3781         if(WINED3DRS_CCW_STENCILFAIL == State) {
3782             stencilFail = action;
3783         }
3784         else if(WINED3DRS_CCW_STENCILZFAIL == State) {
3785             depthFail = action;
3786         }
3787         else if(WINED3DRS_CCW_STENCILPASS == State) {
3788             stencilPass = action;
3789         }
3790
3791         if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3792 #if 0 /* Don't use OpenGL 2.0 calls for now */
3793             if(GL_EXTCALL(glStencilOpSeparate)) {
3794                 GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail, depthFail, stencilPass));
3795                 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
3796             }
3797             else
3798 #endif
3799             if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3800                 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3801                 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3802                 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3803                 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3804                 glStencilOp(stencilFail, depthFail, stencilPass);
3805                 checkGLcall("glStencilOp(...)");
3806             }
3807             else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3808                 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail, depthFail, stencilPass));
3809                 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
3810             } else {
3811                 TRACE("Separate stencil operation not supported on this version of opengl");
3812                 glStencilOp(stencilFail, depthFail, stencilPass);
3813                 checkGLcall("glStencilOp(...)");
3814             }
3815         } else {
3816             glStencilOp(stencilFail, depthFail, stencilPass);
3817             checkGLcall("glStencilOp(...)");
3818         }
3819         break;
3820     }
3821     case WINED3DRS_CCW_STENCILFUNC :
3822     {
3823         GLint func;
3824         GLint ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3825         GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3826
3827         func = GL_ALWAYS;
3828         switch ((D3DCMPFUNC)Value) {
3829             case D3DCMP_NEVER: func = GL_NEVER; break;
3830             case D3DCMP_LESS: func = GL_LESS; break;
3831             case D3DCMP_EQUAL: func = GL_EQUAL; break;
3832             case D3DCMP_LESSEQUAL: func = GL_LEQUAL; break;
3833             case D3DCMP_GREATER: func = GL_GREATER; break;
3834             case D3DCMP_NOTEQUAL: func = GL_NOTEQUAL; break;
3835             case D3DCMP_GREATEREQUAL: func = GL_GEQUAL; break;
3836             case D3DCMP_ALWAYS: func = GL_ALWAYS; break;
3837             default:
3838                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3839         }
3840         This->stencilfunc = func;
3841         if(!This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE]) {
3842 #if 0 /* Don't use OpenGL 2.0 calls for now */
3843             if(GL_EXTCALL(glStencilFuncSeparate)) {
3844                 GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func, ref, mask));
3845                 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
3846             }
3847             else
3848 #endif
3849             if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3850                 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3851                 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3852                 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
3853                 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
3854                 glStencilFunc(func, ref, mask);
3855                 checkGLcall("glStencilFunc(...)");
3856             }
3857             else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3858                 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK, func, ref, mask));
3859                 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
3860             } else {
3861                 TRACE("Separate stencil function not supported on this version of opengl");
3862                 glStencilFunc(func, ref, mask);
3863                 checkGLcall("glStencilFunc(...)");
3864             }
3865         } else {
3866             glStencilFunc(func, ref, mask);
3867             checkGLcall("glStencilFunc(...)");
3868         }
3869         break;
3870     }
3871     case WINED3DRS_DEPTHBIAS :
3872     {
3873         if(Value) {
3874             tmpvalue.d = Value;
3875             glEnable(GL_POLYGON_OFFSET_FILL);
3876             checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
3877             glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
3878             checkGLcall("glPolygonOffset(...)");
3879         } else {
3880             glDisable(GL_POLYGON_OFFSET_FILL);
3881             checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
3882         }
3883         break;
3884     }
3885     case WINED3DRS_SEPARATEALPHABLENDENABLE   :
3886     case WINED3DRS_SRCBLENDALPHA              :
3887     case WINED3DRS_DESTBLENDALPHA             :
3888     case WINED3DRS_BLENDOPALPHA               :
3889     case WINED3DRS_MULTISAMPLEMASK            :
3890     case WINED3DRS_PATCHEDGESTYLE             :
3891     case WINED3DRS_PATCHSEGMENTS              :
3892     case WINED3DRS_DEBUGMONITORTOKEN          :
3893     case WINED3DRS_POSITIONORDER              :
3894     case WINED3DRS_NORMALORDER                :
3895     case WINED3DRS_MINTESSELLATIONLEVEL       :
3896     case WINED3DRS_MAXTESSELLATIONLEVEL       :
3897     case WINED3DRS_ADAPTIVETESS_X             :
3898     case WINED3DRS_ADAPTIVETESS_Y             :
3899     case WINED3DRS_ADAPTIVETESS_Z             :
3900     case WINED3DRS_ADAPTIVETESS_W             :
3901     case WINED3DRS_ENABLEADAPTIVETESSELLATION :
3902     case WINED3DRS_COLORWRITEENABLE1          :
3903     case WINED3DRS_COLORWRITEENABLE2          :
3904     case WINED3DRS_COLORWRITEENABLE3          :
3905     case WINED3DRS_BLENDFACTOR                :
3906     case WINED3DRS_SRGBWRITEENABLE            :
3907         FIXME("(%p)->(%s,%ld) not handled yet\n", This, debug_d3drenderstate(State), Value);
3908         break;
3909     default:
3910         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3911     }
3912
3913     LEAVE_GL();
3914
3915     return WINED3D_OK;
3916 }
3917
3918 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3919     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3920     TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3921     *pValue = This->stateBlock->renderState[State];
3922     return WINED3D_OK;
3923 }
3924
3925 /*****
3926  * Get / Set Sampler States
3927  * TODO: Verify against dx9 definitions
3928  *****/
3929
3930 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3931     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3932     /**
3933     * SetSampler is designed to allow for more than the standard up to 8 textures
3934     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
3935     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3936     *
3937     * http://developer.nvidia.com/object/General_FAQ.html#t6
3938     *
3939     * There are two new settings for GForce
3940     * the sampler one:
3941     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3942     * and the texture one:
3943     * GL_MAX_TEXTURE_COORDS_ARB.
3944     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3945      ******************/
3946     /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3947     TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3948
3949     if(Sampler >  GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3950          FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3951         return WINED3DERR_INVALIDCALL;
3952     }
3953     TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3954     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
3955     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
3956     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3957
3958     /* Handle recording of state blocks */
3959     if (This->isRecordingState) {
3960         TRACE("Recording... not performing anything\n");
3961         return WINED3D_OK;
3962     }
3963
3964     return WINED3D_OK;
3965 }
3966
3967 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3968     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3969     /** TODO: check that sampler is in  range **/
3970     *Value = This->updateStateBlock->samplerState[Sampler][Type];
3971     TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3972
3973     return WINED3D_OK;
3974 }
3975
3976 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3977     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3978     ENTER_GL();
3979
3980     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3981     TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3982     glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3983     LEAVE_GL();
3984
3985     return WINED3D_OK;
3986 }
3987
3988 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3989     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3990     GLint scissorBox[4];
3991
3992     ENTER_GL();
3993     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3994     glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3995     pRect->left = scissorBox[1];
3996     pRect->top = scissorBox[2];
3997     pRect->right = scissorBox[1] + scissorBox[3];
3998     pRect->bottom = scissorBox[2] + scissorBox[4];
3999     TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4000     LEAVE_GL();
4001     return WINED3D_OK;
4002 }
4003
4004 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4005     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4006     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4007
4008     TRACE("(%p) : pDecl=%p\n", This, pDecl);
4009
4010     This->updateStateBlock->vertexDecl = pDecl;
4011     This->updateStateBlock->changed.vertexDecl = TRUE;
4012     This->updateStateBlock->set.vertexDecl = TRUE;
4013
4014     if (This->isRecordingState) {
4015         TRACE("Recording... not performing anything\n");
4016     }
4017
4018     if (NULL != pDecl) {
4019         IWineD3DVertexDeclaration_AddRef(pDecl);
4020     }
4021     if (NULL != oldDecl) {
4022         IWineD3DVertexDeclaration_Release(oldDecl);
4023     }
4024     return WINED3D_OK;
4025 }
4026
4027 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4028     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4029
4030     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4031
4032     *ppDecl = This->stateBlock->vertexDecl;
4033     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4034     return WINED3D_OK;
4035 }
4036
4037 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4038     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
4039     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4040
4041     This->updateStateBlock->vertexShader         = pShader;
4042     This->updateStateBlock->changed.vertexShader = TRUE;
4043     This->updateStateBlock->set.vertexShader     = TRUE;
4044
4045     if (This->isRecordingState) {
4046         TRACE("Recording... not performing anything\n");
4047     }
4048
4049     if (NULL != pShader) {
4050         IWineD3DVertexShader_AddRef(pShader);
4051     }
4052     if (NULL != oldShader) {
4053         IWineD3DVertexShader_Release(oldShader);
4054     }
4055
4056     if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) {
4057         TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4058         IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration);
4059     }
4060
4061     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4062     /**
4063      * TODO: merge HAL shaders context switching from prototype
4064      */
4065     return WINED3D_OK;
4066 }
4067
4068 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4069     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4070
4071     if (NULL == ppShader) {
4072         return WINED3DERR_INVALIDCALL;
4073     }
4074     *ppShader = This->stateBlock->vertexShader;
4075     if( NULL != *ppShader)
4076         IWineD3DVertexShader_AddRef(*ppShader);
4077
4078     TRACE("(%p) : returning %p\n", This, *ppShader);
4079     return WINED3D_OK;
4080 }
4081
4082 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4083     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4084
4085     int i;
4086     int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4087
4088     TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4089             iface, dstData, srcData, type, start, count, registersize);
4090
4091     if (type != WINESHADERCNST_NONE) {
4092         if (srcData == NULL || cnt < 0) {
4093             return WINED3DERR_INVALIDCALL;
4094         }
4095
4096         CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4097     }
4098
4099     for (i = start; i < cnt + start; ++i) {
4100         This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
4101         This->updateStateBlock->set.vertexShaderConstants[i]     = TRUE;
4102         This->updateStateBlock->vertexShaderConstantT[i]         = type;
4103     }
4104
4105     return WINED3D_OK;
4106 }
4107
4108 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4109     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4110
4111     int i;
4112     int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
4113
4114     TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4115             iface, dstData, srcData, type, start, count, registersize);
4116
4117     /* Verify that the requested shader constant was populated with the correct type */
4118     for (i = start; i < cnt + start; ++i) {
4119         if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
4120             TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n", 
4121                     This, type, This->updateStateBlock->vertexShaderConstantT[i]);
4122             return WINED3DERR_INVALIDCALL;
4123         }
4124     }
4125
4126     if (dstData == NULL || cnt < 0) {
4127         return WINED3DERR_INVALIDCALL;
4128     }
4129
4130     CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4131
4132     return WINED3D_OK;
4133 }
4134
4135 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL  *pConstantData, UINT BoolCount){
4136     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4137     
4138     return IWineD3DDeviceImpl_SetVertexShaderConstant(iface, 
4139             This->updateStateBlock->vertexShaderConstantB, 
4140             pConstantData, 
4141             WINESHADERCNST_BOOL, 
4142             StartRegister, 
4143             BoolCount, 
4144             sizeof(*pConstantData));
4145 }
4146
4147 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
4148     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4149     
4150     return IWineD3DDeviceImpl_GetVertexShaderConstant(iface, 
4151             pConstantData, 
4152             This->updateStateBlock->vertexShaderConstantB, 
4153             WINESHADERCNST_BOOL, 
4154             StartRegister, 
4155             BoolCount, 
4156             sizeof(*pConstantData));
4157 }
4158
4159 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
4160     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4161     
4162     return IWineD3DDeviceImpl_SetVertexShaderConstant(iface, 
4163             This->updateStateBlock->vertexShaderConstantI, 
4164             pConstantData, 
4165             WINESHADERCNST_INTEGER, 
4166             StartRegister, 
4167             Vector4iCount, 
4168             4 * sizeof(*pConstantData));
4169 }
4170
4171 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int         *pConstantData, UINT Vector4iCount){
4172     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4173     
4174     return IWineD3DDeviceImpl_GetVertexShaderConstant(iface, 
4175             pConstantData, 
4176             This->updateStateBlock->vertexShaderConstantI, 
4177             WINESHADERCNST_INTEGER, 
4178             StartRegister, 
4179             Vector4iCount, 
4180             4 * sizeof(*pConstantData));
4181 }
4182
4183
4184 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
4185     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4186
4187     return IWineD3DDeviceImpl_SetVertexShaderConstant(iface, 
4188             This->updateStateBlock->vertexShaderConstantF, 
4189             pConstantData, 
4190             WINESHADERCNST_FLOAT, 
4191             StartRegister, 
4192             Vector4fCount, 
4193             4 * sizeof(*pConstantData));
4194 }
4195
4196 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float       *pConstantData, UINT Vector4fCount){
4197     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4198
4199     return IWineD3DDeviceImpl_GetVertexShaderConstant(iface, 
4200             pConstantData, 
4201             This->updateStateBlock->vertexShaderConstantF, 
4202             WINESHADERCNST_FLOAT, 
4203             StartRegister, 
4204             Vector4fCount, 
4205             4 * sizeof(*pConstantData));
4206 }
4207
4208 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4209     return IWineD3DDeviceImpl_SetVertexShaderConstant(iface, 
4210             NULL, 
4211             NULL, 
4212             WINESHADERCNST_NONE, 
4213             StartRegister, 
4214             VectorNCount, 
4215             0);
4216 }
4217
4218 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4219     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
4220     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
4221     This->updateStateBlock->pixelShader         = pShader;
4222     This->updateStateBlock->changed.pixelShader = TRUE;
4223     This->updateStateBlock->set.pixelShader     = TRUE;
4224
4225     /* Handle recording of state blocks */
4226     if (This->isRecordingState) {
4227         TRACE("Recording... not performing anything\n");
4228     }
4229
4230     if (NULL != pShader) {
4231         IWineD3DPixelShader_AddRef(pShader);
4232     }
4233     if (NULL != oldShader) {
4234         IWineD3DPixelShader_Release(oldShader);
4235     }
4236
4237     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4238     /**
4239      * TODO: merge HAL shaders context switching from prototype
4240      */
4241     return WINED3D_OK;
4242 }
4243
4244 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4245     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4246
4247     if (NULL == ppShader) {
4248         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4249         return WINED3DERR_INVALIDCALL;
4250     }
4251
4252     *ppShader =  This->stateBlock->pixelShader;
4253     if (NULL != ppShader) {
4254         IWineD3DPixelShader_AddRef(*ppShader);
4255     }
4256     TRACE("(%p) : returning %p\n", This, *ppShader);
4257     return WINED3D_OK;
4258 }
4259
4260 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4261     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4262
4263     int i;
4264     int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4265
4266     TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4267             iface, dstData, srcData, type, start, count, registersize);
4268
4269     if (type != WINESHADERCNST_NONE) {
4270         if (srcData == NULL || cnt < 0) {
4271             return WINED3DERR_INVALIDCALL;
4272         }
4273
4274         CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4275     }
4276
4277     for (i = start; i < cnt + start; ++i) {
4278         This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4279         This->updateStateBlock->set.pixelShaderConstants[i]     = TRUE;
4280         This->updateStateBlock->pixelShaderConstantT[i]         = type;
4281     }
4282
4283     return WINED3D_OK;
4284 }
4285
4286 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4287     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4288
4289     int i;
4290     int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4291
4292     TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4293             iface, dstData, srcData, type, start, count, registersize);
4294
4295     /* Verify that the requested shader constant was populated with the correct type */
4296     for (i = start; i < cnt + start; ++i) {
4297         if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4298             TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n", 
4299                     This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4300             return WINED3DERR_INVALIDCALL;
4301         }
4302     }
4303
4304     if (dstData == NULL || cnt < 0) {
4305         return WINED3DERR_INVALIDCALL;
4306     }
4307
4308     CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4309
4310     return WINED3D_OK;
4311 }
4312
4313 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL   *pConstantData, UINT BoolCount) {
4314     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4315     
4316     return IWineD3DDeviceImpl_SetPixelShaderConstant(iface, 
4317             This->updateStateBlock->pixelShaderConstantB, 
4318             pConstantData, 
4319             WINESHADERCNST_BOOL, 
4320             StartRegister, 
4321             BoolCount, 
4322             sizeof(*pConstantData));
4323 }
4324
4325 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL         *pConstantData, UINT BoolCount) {
4326     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4327
4328     return IWineD3DDeviceImpl_GetPixelShaderConstant(iface, 
4329             pConstantData, 
4330             This->updateStateBlock->pixelShaderConstantB, 
4331             WINESHADERCNST_BOOL, 
4332             StartRegister, 
4333             BoolCount, 
4334             sizeof(*pConstantData));
4335 }
4336
4337 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int    *pConstantData, UINT Vector4iCount) {
4338     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4339
4340     return IWineD3DDeviceImpl_SetPixelShaderConstant(iface, 
4341             This->updateStateBlock->pixelShaderConstantI, 
4342             pConstantData, 
4343             WINESHADERCNST_INTEGER, 
4344             StartRegister, 
4345             Vector4iCount, 
4346             4 * sizeof(*pConstantData));
4347 }
4348
4349 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int          *pConstantData, UINT Vector4iCount) {
4350     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4351     
4352     return IWineD3DDeviceImpl_GetPixelShaderConstant(iface, 
4353             pConstantData, 
4354             This->updateStateBlock->pixelShaderConstantI, 
4355             WINESHADERCNST_INTEGER, 
4356             StartRegister, 
4357             Vector4iCount, 
4358             4 * sizeof(*pConstantData));
4359 }
4360
4361 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float  *pConstantData, UINT Vector4fCount) {
4362     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4363     
4364     return IWineD3DDeviceImpl_SetPixelShaderConstant(iface, 
4365             This->updateStateBlock->pixelShaderConstantF, 
4366             pConstantData, 
4367             WINESHADERCNST_FLOAT, 
4368             StartRegister, 
4369             Vector4fCount, 
4370             4 * sizeof(*pConstantData));
4371 }
4372
4373 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float        *pConstantData, UINT Vector4fCount) {
4374     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4375
4376     return IWineD3DDeviceImpl_GetPixelShaderConstant(iface, 
4377             pConstantData, 
4378             This->updateStateBlock->pixelShaderConstantF, 
4379             WINESHADERCNST_FLOAT, 
4380             StartRegister, 
4381             Vector4fCount, 
4382             4 * sizeof(*pConstantData));
4383 }
4384
4385 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4386     return IWineD3DDeviceImpl_SetPixelShaderConstant(iface, 
4387             NULL, 
4388             NULL, 
4389             WINESHADERCNST_NONE, 
4390             StartRegister, 
4391             VectorNCount, 
4392             0);
4393 }
4394
4395 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4396     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4397     FIXME("(%p) : stub\n", This);
4398     return WINED3D_OK;
4399 }
4400
4401 /*****
4402  * Apply / Get / Set Texture Stage States
4403  * TODO: Verify against dx9 definitions
4404  *****/
4405
4406 /* NOTE: It's expected that this function is going to be called lots of times with the same stage active, so make it the callers responsibility to GLACTIVETEXTURE(Stage) for better state management. Set the correct Texture unit active before calling ApplyTextureStageState */
4407 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4408     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4409     DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4410     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4411
4412     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4413
4414     /* Check that the stage is within limits  */
4415     if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4416         TRACE("Attempt to access invalid texture rejected\n");
4417         return;
4418     }
4419
4420     ENTER_GL();
4421
4422     switch (Type) {
4423     case WINED3DTSS_ALPHAOP               :
4424     case WINED3DTSS_COLOROP               :
4425         /* nothing to do as moved to drawprim for now */
4426         break;
4427     case WINED3DTSS_ADDRESSW              :
4428 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4429             if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4430                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4431
4432             } else {
4433                 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4434                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4435                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4436                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4437             }
4438 #endif
4439     case WINED3DTSS_TEXCOORDINDEX         :
4440         {
4441             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4442
4443             /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4444                   one flag, you can still specify an index value, which the system uses to
4445                   determine the texture wrapping mode.
4446                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4447                   means use the vertex position (camera-space) as the input texture coordinates
4448                   for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4449                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4450                   to the TEXCOORDINDEX value */
4451
4452             /**
4453              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4454              */
4455             switch (Value & 0xFFFF0000) {
4456             case D3DTSS_TCI_PASSTHRU:
4457                 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4458                 glDisable(GL_TEXTURE_GEN_S);
4459                 glDisable(GL_TEXTURE_GEN_T);
4460                 glDisable(GL_TEXTURE_GEN_R);
4461                 glDisable(GL_TEXTURE_GEN_Q);
4462                 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4463                 break;
4464
4465             case D3DTSS_TCI_CAMERASPACEPOSITION:
4466                 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4467                     as the input texture coordinates for this stage's texture transformation. This
4468                     equates roughly to EYE_LINEAR                                                  */
4469                 {
4470                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4471                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4472                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4473                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4474                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4475     
4476                     glMatrixMode(GL_MODELVIEW);
4477                     glPushMatrix();
4478                     glLoadIdentity();
4479                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4480                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4481                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4482                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4483                     glPopMatrix();
4484     
4485                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4486                     glEnable(GL_TEXTURE_GEN_S);
4487                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4488                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4489                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4490                     glEnable(GL_TEXTURE_GEN_T);
4491                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4492                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4493                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4494                     glEnable(GL_TEXTURE_GEN_R);
4495                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4496                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4497                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4498                 }
4499                 break;
4500
4501             case D3DTSS_TCI_CAMERASPACENORMAL:
4502                 {
4503                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4504                         float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4505                         float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4506                         float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4507                         float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4508                         TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4509         
4510                         glMatrixMode(GL_MODELVIEW);
4511                         glPushMatrix();
4512                         glLoadIdentity();
4513                         glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4514                         glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4515                         glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4516                         glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4517                         glPopMatrix();
4518         
4519                         glEnable(GL_TEXTURE_GEN_S);
4520                         checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4521                         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4522                         checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4523                         glEnable(GL_TEXTURE_GEN_T);
4524                         checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4525                         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4526                         checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4527                         glEnable(GL_TEXTURE_GEN_R);
4528                         checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4529                         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4530                         checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4531                     }
4532                 }
4533                 break;
4534
4535             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4536                 {
4537                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4538                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4539                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4540                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4541                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4542                     TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4543     
4544                     glMatrixMode(GL_MODELVIEW);
4545                     glPushMatrix();
4546                     glLoadIdentity();
4547                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4548                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4549                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4550                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4551                     glPopMatrix();
4552     
4553                     glEnable(GL_TEXTURE_GEN_S);
4554                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4555                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4556                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4557                     glEnable(GL_TEXTURE_GEN_T);
4558                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4559                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4560                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4561                     glEnable(GL_TEXTURE_GEN_R);
4562                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4563                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4564                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4565                     }
4566                 }
4567                 break;
4568
4569             /* Unhandled types: */
4570             default:
4571                 /* Todo: */
4572                 /* ? disable GL_TEXTURE_GEN_n ? */
4573                 glDisable(GL_TEXTURE_GEN_S);
4574                 glDisable(GL_TEXTURE_GEN_T);
4575                 glDisable(GL_TEXTURE_GEN_R);
4576                 glDisable(GL_TEXTURE_GEN_Q);
4577                 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4578                 break;
4579             }
4580         }
4581         break;
4582
4583         /* Unhandled */
4584     case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4585         set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
4586         break;
4587
4588     case WINED3DTSS_BUMPENVMAT00          :
4589     case WINED3DTSS_BUMPENVMAT01          :
4590         TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4591         break;
4592     case WINED3DTSS_BUMPENVMAT10          :
4593     case WINED3DTSS_BUMPENVMAT11          :
4594         TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4595         break;
4596
4597     case WINED3DTSS_BUMPENVLSCALE         :
4598       TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4599       break;
4600
4601     case WINED3DTSS_BUMPENVLOFFSET        :
4602       TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4603       break;
4604
4605     case WINED3DTSS_RESULTARG             :
4606       TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4607       break;
4608
4609     default:
4610         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4611         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4612     }
4613
4614     LEAVE_GL();
4615
4616     return;
4617 }
4618
4619 /*****
4620  * Get / Set Texture Stage States
4621  * TODO: Verify against dx9 definitions
4622  *****/
4623 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4624     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4625
4626     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4627
4628     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4629
4630     /* Reject invalid texture units */
4631     if (Stage >= GL_LIMITS(textures)) {
4632         TRACE("Attempt to access invalid texture rejected\n");
4633         return WINED3DERR_INVALIDCALL;
4634     }
4635
4636     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4637     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
4638     This->updateStateBlock->textureState[Stage][Type]         = Value;
4639
4640     return WINED3D_OK;
4641 }
4642
4643 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4644     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4645     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4646     *pValue = This->updateStateBlock->textureState[Stage][Type];
4647     return WINED3D_OK;
4648 }
4649
4650 /*****
4651  * Get / Set Texture
4652  *****/
4653 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4654
4655     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656     IWineD3DBaseTexture   *oldTexture;
4657
4658     oldTexture = This->updateStateBlock->textures[Stage];
4659     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4660
4661 #if 0 /* TODO: check so vertex textures */
4662     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4663         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4664         return WINED3D_OK;
4665     }
4666 #endif
4667
4668     /* Reject invalid texture units */
4669     if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4670         WARN("Attempt to access invalid texture rejected\n");
4671         return WINED3DERR_INVALIDCALL;
4672     }
4673
4674     if(pTexture != NULL) {
4675         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; The same is
4676         *  the case for WINED3DPOOL_SYSTEMMEM textures unless WINED3DDEVCAPS_TEXTURESYSTEMMORY is set.
4677         *  We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4678         */
4679         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SYSTEMMEM) {
4680             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4681             return WINED3DERR_INVALIDCALL;
4682         }
4683     }
4684
4685     oldTexture = This->updateStateBlock->textures[Stage];
4686     TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4687     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4688
4689     This->updateStateBlock->set.textures[Stage]     = TRUE;
4690     This->updateStateBlock->changed.textures[Stage] = TRUE;
4691     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4692     This->updateStateBlock->textures[Stage]         = pTexture;
4693
4694     /* Handle recording of state blocks */
4695     if (This->isRecordingState) {
4696         TRACE("Recording... not performing anything\n");
4697         return WINED3D_OK;
4698     }
4699
4700     /** NOTE: MSDN says that setTexture increases the reference count,
4701     * and the the application nust set the texture back to null (or have a leaky application),
4702     * This means we should pass the refcount up to the parent
4703      *******************************/
4704     if (NULL != This->updateStateBlock->textures[Stage]) {
4705         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4706     }
4707
4708     if (NULL != oldTexture) {
4709         IWineD3DBaseTexture_Release(oldTexture);
4710     }
4711
4712     return WINED3D_OK;
4713 }
4714
4715 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4716     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4717     TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4718
4719     /* Reject invalid texture units */
4720     if (Stage >= GL_LIMITS(textures)) {
4721         TRACE("Attempt to access invalid texture rejected\n");
4722         return WINED3DERR_INVALIDCALL;
4723     }
4724     *ppTexture=This->updateStateBlock->textures[Stage];
4725     if (*ppTexture)
4726         IWineD3DBaseTexture_AddRef(*ppTexture);
4727     else
4728         return WINED3DERR_INVALIDCALL;
4729     return WINED3D_OK;
4730 }
4731
4732 /*****
4733  * Get Back Buffer
4734  *****/
4735 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4736                                                 IWineD3DSurface **ppBackBuffer) {
4737     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4738     IWineD3DSwapChain *swapChain;
4739     HRESULT hr;
4740
4741     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4742
4743     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4744     if (hr == WINED3D_OK) {
4745         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4746             IWineD3DSwapChain_Release(swapChain);
4747     } else {
4748         *ppBackBuffer = NULL;
4749     }
4750     return hr;
4751 }
4752
4753 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4754     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4755     WARN("(%p) : stub, calling idirect3d for now\n", This);
4756     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4757 }
4758
4759 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4760     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4761     IWineD3DSwapChain *swapChain;
4762     HRESULT hr;
4763
4764     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4765     if (hr == WINED3D_OK) {
4766         hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4767         IWineD3DSwapChain_Release(swapChain);
4768     } else {
4769         FIXME("(%p) Error getting display mode\n", This);
4770     }
4771     return hr;
4772 }
4773 /*****
4774  * Stateblock related functions
4775  *****/
4776
4777 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4778     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4779     IWineD3DStateBlockImpl *object;
4780     TRACE("(%p)", This);
4781     
4782     if (This->isRecordingState) {
4783         return WINED3DERR_INVALIDCALL;
4784     }
4785     
4786     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4787     if (NULL == object ) {
4788         FIXME("(%p)Error allocating memory for stateblock\n", This);
4789         return E_OUTOFMEMORY;
4790     }
4791     TRACE("(%p) creted object %p\n", This, object);
4792     object->wineD3DDevice= This;
4793     /** FIXME: object->parent       = parent; **/
4794     object->parent       = NULL;
4795     object->blockType    = WINED3DSBT_ALL;
4796     object->ref          = 1;
4797     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4798
4799     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4800     This->updateStateBlock = object;
4801     This->isRecordingState = TRUE;
4802
4803     TRACE("(%p) recording stateblock %p\n",This , object);
4804     return WINED3D_OK;
4805 }
4806
4807 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4808     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4809
4810     if (!This->isRecordingState) {
4811         FIXME("(%p) not recording! returning error\n", This);
4812         *ppStateBlock = NULL;
4813         return WINED3DERR_INVALIDCALL;
4814     }
4815
4816     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4817     This->isRecordingState = FALSE;
4818     This->updateStateBlock = This->stateBlock;
4819     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4820     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4821     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4822     return WINED3D_OK;
4823 }
4824
4825 /*****
4826  * Scene related functions
4827  *****/
4828 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4829     /* At the moment we have no need for any functionality at the beginning
4830        of a scene                                                          */
4831     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4832     TRACE("(%p) : stub\n", This);
4833     return WINED3D_OK;
4834 }
4835
4836 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4837     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4838     TRACE("(%p)\n", This);
4839     ENTER_GL();
4840     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4841     glFlush();
4842     checkGLcall("glFlush");
4843
4844     TRACE("End Scene\n");
4845     if(This->renderTarget != NULL) {
4846
4847         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4848         IUnknown *targetContainer = NULL;
4849         if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4850             || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4851             TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4852             /** always dirtify for now. we must find a better way to see that surface have been modified
4853             (Modifications should will only occur via draw-primitive, but we do need better locking
4854             switching to render-to-texture should remove the overhead though.
4855             */
4856             IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4857             IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4858             IWineD3DSurface_PreLoad(This->renderTarget);
4859             IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4860             IUnknown_Release(targetContainer);
4861         }
4862     }
4863     This->sceneEnded = TRUE;
4864     LEAVE_GL();
4865     return WINED3D_OK;
4866 }
4867
4868 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4869                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4870                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4871     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4872     IWineD3DSwapChain *swapChain = NULL;
4873     int i;
4874     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4875
4876     TRACE("(%p) Presenting the frame\n", This);
4877
4878     for(i = 0 ; i < swapchains ; i ++) {
4879
4880         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4881         TRACE("presentinng chain %d, %p\n", i, swapChain);
4882         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4883         IWineD3DSwapChain_Release(swapChain);
4884     }
4885
4886     return WINED3D_OK;
4887 }
4888
4889 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4890                                         DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4891     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4892
4893     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4894       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4895       when the depth-buffer format does not contain stencil buffer information, this method fails. */
4896     GLbitfield     glMask = 0;
4897     GLboolean      old_ztest;
4898     GLfloat        old_z_clear_value;
4899     GLint          old_stencil_clear_value;
4900     GLfloat        old_color_clear_value[4];
4901     unsigned int   i;
4902     CONST D3DRECT* curRect;
4903
4904     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4905           Count, pRects, Flags, Z, Stencil);
4906
4907     ENTER_GL();
4908
4909     glEnable(GL_SCISSOR_TEST);
4910     checkGLcall("glEnable GL_SCISSOR_TEST");
4911
4912     if (Count > 0 && pRects) {
4913         curRect = pRects;
4914     } else {
4915         curRect = NULL;
4916     }
4917
4918     /* Only set the values up once, as they are not changing */
4919     if (Flags & D3DCLEAR_STENCIL) {
4920         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4921         glClearStencil(Stencil);
4922         checkGLcall("glClearStencil");
4923         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4924         glStencilMask(0xFFFFFFFF);
4925     }
4926
4927     if (Flags & D3DCLEAR_ZBUFFER) {
4928         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4929         glDepthMask(GL_TRUE);
4930         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4931         glClearDepth(Z);
4932         checkGLcall("glClearDepth");
4933         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4934     }
4935
4936     if (Flags & D3DCLEAR_TARGET) {
4937         TRACE("Clearing screen with glClear to color %lx\n", Color);
4938         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4939         glClearColor(D3DCOLOR_R(Color),
4940                      D3DCOLOR_G(Color),
4941                      D3DCOLOR_B(Color),
4942                      D3DCOLOR_A(Color));
4943         checkGLcall("glClearColor");
4944
4945         /* Clear ALL colors! */
4946         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4947         glMask = glMask | GL_COLOR_BUFFER_BIT;
4948     }
4949
4950     /* Now process each rect in turn */
4951     for (i = 0; i < Count || i == 0; i++) {
4952
4953         if (curRect) {
4954             /* Note gl uses lower left, width/height */
4955             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4956                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4957                   curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4958                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4959             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4960                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4961             checkGLcall("glScissor");
4962         } else {
4963             glScissor(This->stateBlock->viewport.X,
4964                       (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - 
4965                       (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4966                       This->stateBlock->viewport.Width,
4967                       This->stateBlock->viewport.Height);
4968             checkGLcall("glScissor");
4969         }
4970
4971         /* Clear the selected rectangle (or full screen) */
4972         glClear(glMask);
4973         checkGLcall("glClear");
4974
4975         /* Step to the next rectangle */
4976         if (curRect) curRect = curRect + sizeof(D3DRECT);
4977     }
4978
4979     /* Restore the old values (why..?) */
4980     if (Flags & D3DCLEAR_STENCIL) {
4981         glClearStencil(old_stencil_clear_value);
4982         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4983     }
4984     if (Flags & D3DCLEAR_ZBUFFER) {
4985         glDepthMask(old_ztest);
4986         glClearDepth(old_z_clear_value);
4987     }
4988     if (Flags & D3DCLEAR_TARGET) {
4989         glClearColor(old_color_clear_value[0],
4990                      old_color_clear_value[1],
4991                      old_color_clear_value[2],
4992                      old_color_clear_value[3]);
4993         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4994                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4995                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4996                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4997     }
4998
4999     glDisable(GL_SCISSOR_TEST);
5000     checkGLcall("glDisable");
5001     LEAVE_GL();
5002
5003     return WINED3D_OK;
5004 }
5005
5006 /*****
5007  * Drawing functions
5008  *****/
5009 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5010                                                 UINT PrimitiveCount) {
5011
5012     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5013     This->stateBlock->streamIsUP = FALSE;
5014
5015     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5016                                debug_d3dprimitivetype(PrimitiveType),
5017                                StartVertex, PrimitiveCount);
5018     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5019                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5020
5021
5022     return WINED3D_OK;
5023 }
5024
5025 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5026 HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5027                                                            D3DPRIMITIVETYPE PrimitiveType,
5028                                                            INT baseVIndex, UINT minIndex,
5029                                                            UINT NumVertices, UINT startIndex, UINT primCount) {
5030
5031     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
5032     UINT                 idxStride = 2;
5033     IWineD3DIndexBuffer *pIB;
5034     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
5035
5036     pIB = This->stateBlock->pIndexData;
5037     This->stateBlock->streamIsUP = FALSE;
5038
5039     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5040           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5041           minIndex, NumVertices, startIndex, baseVIndex, primCount);
5042
5043     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5044     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5045         idxStride = 2;
5046     } else {
5047         idxStride = 4;
5048     }
5049
5050     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5051                    idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5052
5053     return WINED3D_OK;
5054 }
5055
5056 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5057                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5058                                                     UINT VertexStreamZeroStride) {
5059     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5060
5061     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5062              debug_d3dprimitivetype(PrimitiveType),
5063              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5064
5065     /* release the stream source */
5066     if (This->stateBlock->streamSource[0] != NULL) {
5067         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5068     }
5069
5070     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5071     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5072     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5073     This->stateBlock->streamIsUP = TRUE;
5074
5075     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
5076                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5077     /* stream zero settings set to null at end, as per the msdn
5078             http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5079     */
5080     This->stateBlock->streamStride[0] = 0;
5081     This->stateBlock->streamSource[0] = NULL;
5082
5083     /*stream zero settings set to null at end, as per the msdn */
5084     return WINED3D_OK;
5085 }
5086
5087 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
5088                                                              UINT MinVertexIndex, UINT NumVertices,
5089                                                              UINT PrimitiveCount, CONST void* pIndexData,
5090                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5091                                                              UINT VertexStreamZeroStride) {
5092     int                 idxStride;
5093     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5094
5095     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5096              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5097              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5098              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5099
5100     if (IndexDataFormat == WINED3DFMT_INDEX16) {
5101         idxStride = 2;
5102     } else {
5103         idxStride = 4;
5104     }
5105
5106     /* release the stream and index data */
5107     if (This->stateBlock->streamSource[0] != NULL) {
5108         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5109     }
5110     if (This->stateBlock->pIndexData) {
5111         IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5112     }
5113
5114     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5115     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5116     This->stateBlock->streamIsUP = TRUE;
5117     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5118
5119     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5120     /* stream zero settings set to null at end as per the msdn
5121     http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
5122     */
5123
5124     /* stream zero settings set to null at end as per the msdn */
5125     This->stateBlock->streamSource[0] = NULL;
5126     This->stateBlock->streamStride[0] = 0;
5127
5128     return WINED3D_OK;
5129 }
5130
5131  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5132 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
5133     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5134     HRESULT hr = WINED3D_OK;
5135     WINED3DRESOURCETYPE sourceType;
5136     WINED3DRESOURCETYPE destinationType;
5137     int i ,levels;
5138
5139     /* TODO: think about moving the code into IWineD3DBaseTexture  */
5140
5141     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5142
5143     /* verify that the source and destination textures aren't NULL */
5144     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5145         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5146              This, pSourceTexture, pDestinationTexture);
5147         hr = WINED3DERR_INVALIDCALL;
5148     }
5149
5150     if (pSourceTexture == pDestinationTexture) {
5151         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5152              This, pSourceTexture, pDestinationTexture);
5153         hr = WINED3DERR_INVALIDCALL;
5154     }
5155     /* Verify that the source and destination textures are the same type */
5156     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5157     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5158
5159     if (sourceType != destinationType) {
5160         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5161              This);
5162         hr = WINED3DERR_INVALIDCALL;
5163     }
5164
5165     /* check that both textures have the identical numbers of levels  */
5166     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5167         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5168         hr = WINED3DERR_INVALIDCALL;
5169     }
5170
5171     if (WINED3D_OK == hr) {
5172
5173         /* Make sure that the destination texture is loaded */
5174         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5175
5176         /* Update every surface level of the texture */
5177         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5178
5179         switch (sourceType) {
5180         case WINED3DRTYPE_TEXTURE:
5181             {
5182                 IWineD3DSurface *srcSurface;
5183                 IWineD3DSurface *destSurface;
5184
5185                 for (i = 0 ; i < levels ; ++i) {
5186                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
5187                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5188                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5189                     IWineD3DSurface_Release(srcSurface);
5190                     IWineD3DSurface_Release(destSurface);
5191                     if (WINED3D_OK != hr) {
5192                         WARN("(%p) : Call to update surface failed\n", This);
5193                         return hr;
5194                     }
5195                 }
5196             }
5197             break;
5198         case WINED3DRTYPE_CUBETEXTURE:
5199             {
5200                 IWineD3DSurface *srcSurface;
5201                 IWineD3DSurface *destSurface;
5202                 WINED3DCUBEMAP_FACES faceType;
5203
5204                 for (i = 0 ; i < levels ; ++i) {
5205                     /* Update each cube face */
5206                     for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5207                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
5208                         if (WINED3D_OK != hr) {
5209                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5210                         } else {
5211                             TRACE("Got srcSurface %p\n", srcSurface);
5212                         }
5213                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5214                         if (WINED3D_OK != hr) {
5215                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5216                         } else {
5217                             TRACE("Got desrSurface %p\n", destSurface);
5218                         }
5219                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5220                         IWineD3DSurface_Release(srcSurface);
5221                         IWineD3DSurface_Release(destSurface);
5222                         if (WINED3D_OK != hr) {
5223                             WARN("(%p) : Call to update surface failed\n", This);
5224                             return hr;
5225                         }
5226                     }
5227                 }
5228             }
5229             break;
5230 #if 0 /* TODO: Add support for volume textures */
5231         case WINED3DRTYPE_VOLUMETEXTURE:
5232             {
5233                 IWineD3DVolume  srcVolume  = NULL;
5234                 IWineD3DSurface destVolume = NULL;
5235
5236                 for (i = 0 ; i < levels ; ++i) {
5237                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5238                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5239                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5240                     IWineD3DVolume_Release(srcSurface);
5241                     IWineD3DVolume_Release(destSurface);
5242                     if (WINED3D_OK != hr) {
5243                         WARN("(%p) : Call to update volume failed\n", This);
5244                         return hr;
5245                     }
5246                 }
5247             }
5248             break;
5249 #endif
5250         default:
5251             FIXME("(%p) : Unsupported source and destination type\n", This);
5252             hr = WINED3DERR_INVALIDCALL;
5253         }
5254     }
5255
5256     return hr;
5257 }
5258
5259 HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5260                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5261                                                 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5262     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5263
5264     TRACE("(%p) : stub\n", This);
5265     return WINED3D_OK;
5266 }
5267 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5268     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5269     /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5270     *  NOTE It may be best to move the code into surface to occomplish this
5271     ****************************************/
5272
5273     WINED3DSURFACE_DESC surfaceDesc;
5274     unsigned int surfaceWidth, surfaceHeight;
5275     glDescriptor *targetGlDescription  = NULL;
5276     glDescriptor *surfaceGlDescription = NULL;
5277     IWineD3DSwapChainImpl *container = NULL;
5278     
5279     IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5280     IWineD3DSurface_GetGlDesc(pSurface,      &surfaceGlDescription);
5281     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5282
5283     surfaceDesc.Width  = &surfaceWidth;
5284     surfaceDesc.Height = &surfaceHeight;
5285     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5286    /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5287
5288     /* Ok, I may need to setup some kind of active swapchain reference on the device */
5289     IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5290     ENTER_GL();
5291     /* TODO: opengl Context switching for swapchains etc... */
5292     if (NULL != container  || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5293         if (NULL != container  && (pRenderTarget == container->backBuffer)) {
5294             glReadBuffer(GL_BACK);
5295             vcheckGLcall("glReadBuffer(GL_BACK)");
5296         } else if ((NULL != container  && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5297             glReadBuffer(GL_FRONT);
5298             vcheckGLcall("glReadBuffer(GL_FRONT)");
5299         } else if (pRenderTarget == This->depthStencilBuffer) {
5300             FIXME("Reading of depthstencil not yet supported\n");
5301         }
5302
5303         glReadPixels(surfaceGlDescription->target,
5304                     surfaceGlDescription->level,
5305                     surfaceWidth,
5306                     surfaceHeight,
5307                     surfaceGlDescription->glFormat,
5308                     surfaceGlDescription->glType,
5309                     (void *)IWineD3DSurface_GetData(pSurface));
5310         vcheckGLcall("glReadPixels(...)");
5311         if(NULL != container ){
5312             IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5313         }
5314     } else {
5315         IWineD3DBaseTexture *container;
5316         GLenum textureDimensions = GL_TEXTURE_2D;
5317
5318         if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5319             textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5320             IWineD3DBaseTexture_Release(container);
5321         }
5322         /* TODO: 2D -> Cube surface coppies etc.. */
5323         if (surfaceGlDescription->target != textureDimensions) {
5324             FIXME("(%p) : Texture dimension mismatch\n", This);
5325         }
5326         glEnable(textureDimensions);
5327         vcheckGLcall("glEnable(GL_TEXTURE_...)");
5328         /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5329         glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5330         vcheckGLcall("glBindTexture");
5331         glGetTexImage(surfaceGlDescription->target,
5332                         surfaceGlDescription->level,
5333                         surfaceGlDescription->glFormat,
5334                         surfaceGlDescription->glType,
5335                         (void *)IWineD3DSurface_GetData(pSurface));
5336         glDisable(textureDimensions);
5337         vcheckGLcall("glDisable(GL_TEXTURE_...)");
5338
5339     }
5340     LEAVE_GL();
5341     return WINED3D_OK;
5342 }
5343
5344 HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5345     IWineD3DSwapChain *swapChain;
5346     HRESULT hr;
5347     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5348     if(hr == WINED3D_OK) {
5349         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5350                 IWineD3DSwapChain_Release(swapChain);
5351     }
5352     return hr;
5353 }
5354
5355 HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5356     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5357     /* return a sensible default */
5358     *pNumPasses = 1;
5359     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5360     FIXME("(%p) : stub\n", This);
5361     return WINED3D_OK;
5362 }
5363
5364 HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5365     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5366     int j;
5367     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5368     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5369         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5370         return WINED3DERR_INVALIDCALL;
5371     }
5372     for (j = 0; j < 256; ++j) {
5373         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5374         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5375         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5376         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5377     }
5378     TRACE("(%p) : returning\n", This);
5379     return WINED3D_OK;
5380 }
5381
5382 HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5383     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5384     int j;
5385     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5386     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5387         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5388         return WINED3DERR_INVALIDCALL;
5389     }
5390     for (j = 0; j < 256; ++j) {
5391         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5392         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5393         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5394         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5395     }
5396     TRACE("(%p) : returning\n", This);
5397     return WINED3D_OK;
5398 }
5399
5400 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5401     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5402     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5403     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5404         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5405         return WINED3DERR_INVALIDCALL;
5406     }
5407     /*TODO: stateblocks */
5408     This->currentPalette = PaletteNumber;
5409     TRACE("(%p) : returning\n", This);
5410     return WINED3D_OK;
5411 }
5412
5413 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5414     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5415     if (PaletteNumber == NULL) {
5416         WARN("(%p) : returning Invalid Call\n", This);
5417         return WINED3DERR_INVALIDCALL;
5418     }
5419     /*TODO: stateblocks */
5420     *PaletteNumber = This->currentPalette;
5421     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5422     return WINED3D_OK;
5423 }
5424
5425 HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5426     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5427     static BOOL showFixmes = TRUE;
5428     if (showFixmes) {
5429         FIXME("(%p) : stub\n", This);
5430         showFixmes = FALSE;
5431     }
5432
5433     This->softwareVertexProcessing = bSoftware;
5434     return WINED3D_OK;
5435 }
5436
5437
5438 BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5439     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5440     static BOOL showFixmes = TRUE;
5441     if (showFixmes) {
5442         FIXME("(%p) : stub\n", This);
5443         showFixmes = FALSE;
5444     }
5445     return This->softwareVertexProcessing;
5446 }
5447
5448
5449 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5450     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5451     IWineD3DSwapChain *swapChain;
5452     HRESULT hr;
5453
5454     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5455
5456     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5457     if(hr == WINED3D_OK){
5458         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5459         IWineD3DSwapChain_Release(swapChain);
5460     }else{
5461         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5462     }
5463     return hr;
5464 }
5465
5466
5467 HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5468     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5469     static BOOL showfixmes = TRUE;
5470     if(nSegments != 0.0f) {
5471         if( showfixmes) {
5472             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5473             showfixmes = FALSE;
5474         }
5475     }
5476     return WINED3D_OK;
5477 }
5478
5479 float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5480     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5481     static BOOL showfixmes = TRUE;
5482     if( showfixmes) {
5483         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5484         showfixmes = FALSE;
5485     }
5486     return 0.0f;
5487 }
5488
5489 HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5490     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5491     /** TODO: remove casts to IWineD3DSurfaceImpl
5492      *       NOTE: move code to surface to accomplish this
5493       ****************************************/
5494     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5495     int srcWidth, srcHeight;
5496     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5497     WINED3DFORMAT destFormat, srcFormat;
5498     UINT          destSize;
5499     int destLeft, destTop;
5500     WINED3DPOOL       srcPool, destPool;
5501     int offset    = 0;
5502     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5503     glDescriptor *glDescription = NULL;
5504     GLenum textureDimensions = GL_TEXTURE_2D;
5505     IWineD3DBaseTexture *baseTexture;
5506
5507     WINED3DSURFACE_DESC  winedesc;
5508
5509     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5510     memset(&winedesc, 0, sizeof(winedesc));
5511     winedesc.Width  = &srcSurfaceWidth;
5512     winedesc.Height = &srcSurfaceHeight;
5513     winedesc.Pool   = &srcPool;
5514     winedesc.Format = &srcFormat;
5515
5516     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5517
5518     winedesc.Width  = &destSurfaceWidth;
5519     winedesc.Height = &destSurfaceHeight;
5520     winedesc.Pool   = &destPool;
5521     winedesc.Format = &destFormat;
5522     winedesc.Size   = &destSize;
5523
5524     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5525
5526     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5527         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5528         return WINED3DERR_INVALIDCALL;
5529     }
5530
5531     if (destFormat == WINED3DFMT_UNKNOWN) {
5532         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5533         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5534
5535         /* Get the update surface description */
5536         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5537     }
5538
5539     /* Make sure the surface is loaded and up to date */
5540     IWineD3DSurface_PreLoad(pDestinationSurface);
5541
5542     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5543
5544     ENTER_GL();
5545
5546     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5547     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5548     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
5549     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5550     destTop    = pDestPoint  ? pDestPoint->y : 0;
5551
5552
5553     /* This function doesn't support compressed textures
5554     the pitch is just bytesPerPixel * width */
5555     if(srcWidth != srcSurfaceWidth  || (pSourceRect != NULL && pSourceRect->left != 0) ){
5556         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5557         offset   += pSourceRect->left * pSrcSurface->bytesPerPixel;
5558         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5559     }
5560     /* TODO DXT formats */
5561
5562     if(pSourceRect != NULL && pSourceRect->top != 0){
5563        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5564     }
5565     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5566     ,This
5567     ,glDescription->level
5568     ,destLeft
5569     ,destTop
5570     ,srcWidth
5571     ,srcHeight
5572     ,glDescription->glFormat
5573     ,glDescription->glType
5574     ,IWineD3DSurface_GetData(pSourceSurface)
5575     );
5576
5577     /* Sanity check */
5578     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5579
5580         /* need to lock the surface to get the data */
5581         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5582     }
5583
5584     /* TODO: Cube and volume support */
5585     if(rowoffset != 0){
5586         /* not a whole row so we have to do it a line at a time */
5587         int j;
5588
5589         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5590         unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5591
5592         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5593
5594                 glTexSubImage2D(glDescription->target
5595                     ,glDescription->level
5596                     ,destLeft
5597                     ,j
5598                     ,srcWidth
5599                     ,1
5600                     ,glDescription->glFormat
5601                     ,glDescription->glType
5602                     ,data /* could be quicker using */
5603                 );
5604             data += rowoffset;
5605         }
5606
5607     } else { /* Full width, so just write out the whole texture */
5608
5609         if (WINED3DFMT_DXT1 == destFormat ||
5610             WINED3DFMT_DXT2 == destFormat ||
5611             WINED3DFMT_DXT3 == destFormat ||
5612             WINED3DFMT_DXT4 == destFormat ||
5613             WINED3DFMT_DXT5 == destFormat) {
5614             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5615                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5616                     /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5617                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5618                 } if (destFormat != srcFormat) {
5619                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5620                 } else {
5621                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5622                                                         glDescription->level,
5623                                                         glDescription->glFormatInternal,
5624                                                         srcWidth,
5625                                                         srcHeight,
5626                                                         0,
5627                                                         destSize,
5628                                                         IWineD3DSurface_GetData(pSourceSurface));
5629                 }
5630             } else {
5631                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5632             }
5633
5634
5635         } else {
5636             if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5637
5638                 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5639                 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5640                 data returned by GetData non-power2 width/height with hardware non-power2
5641                 pow2Width/height are set to surface width height, repacking isn't needed so it
5642                 doesn't matter which function gets called. */
5643                 glTexSubImage2D(glDescription->target
5644                         ,glDescription->level
5645                         ,destLeft
5646                         ,destTop
5647                         ,srcWidth
5648                         ,srcHeight
5649                         ,glDescription->glFormat
5650                         ,glDescription->glType
5651                         ,IWineD3DSurface_GetData(pSourceSurface)
5652                     );
5653             } else {
5654
5655                 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5656                 glTexSubImage2D(glDescription->target
5657                     ,glDescription->level
5658                     ,destLeft
5659                     ,destTop
5660                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5661                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5662                     ,glDescription->glFormat
5663                     ,glDescription->glType
5664                     ,IWineD3DSurface_GetData(pSourceSurface)
5665                 );
5666             }
5667
5668         }
5669      }
5670     checkGLcall("glTexSubImage2D");
5671
5672     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5673      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5674      * surface bigger than it needs to be hmm.. */
5675     if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5676         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5677         IWineD3DBaseTexture_Release(baseTexture);
5678     }
5679
5680     glDisable(textureDimensions); /* This needs to be managed better.... */
5681     LEAVE_GL();
5682
5683     return WINED3D_OK;
5684 }
5685
5686 /* Used by DirectX 8 */
5687 HRESULT  WINAPI  IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5688                                                 IWineD3DSurface* pSourceSurface,      CONST RECT* pSourceRectsArray, UINT cRects,
5689                                                 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5690
5691     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
5692     HRESULT              hr = WINED3D_OK;
5693     WINED3DFORMAT        srcFormat, destFormat;
5694     UINT                 srcWidth,  destWidth;
5695     UINT                 srcHeight, destHeight;
5696     UINT                 srcSize;
5697     WINED3DSURFACE_DESC  winedesc;
5698
5699     TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5700           pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5701
5702
5703     /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
5704     memset(&winedesc, 0, sizeof(winedesc));
5705
5706     winedesc.Format = &srcFormat;
5707     winedesc.Width  = &srcWidth;
5708     winedesc.Height = &srcHeight;
5709     winedesc.Size   = &srcSize;
5710     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5711
5712     winedesc.Format = &destFormat;
5713     winedesc.Width  = &destWidth;
5714     winedesc.Height = &destHeight;
5715     winedesc.Size   = NULL;
5716     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5717
5718     /* Check that the source and destination formats match */
5719     if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5720         WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5721         return WINED3DERR_INVALIDCALL;
5722     } else if (WINED3DFMT_UNKNOWN == destFormat) {
5723         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5724         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5725         destFormat = srcFormat;
5726     }
5727
5728     /* Quick if complete copy ... */
5729     if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5730
5731         if (srcWidth == destWidth && srcHeight == destHeight) {
5732             WINED3DLOCKED_RECT lrSrc;
5733             WINED3DLOCKED_RECT lrDst;
5734             IWineD3DSurface_LockRect(pSourceSurface,      &lrSrc, NULL, WINED3DLOCK_READONLY);
5735             IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5736             TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5737
5738             memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
5739
5740             IWineD3DSurface_UnlockRect(pSourceSurface);
5741             IWineD3DSurface_UnlockRect(pDestinationSurface);
5742             TRACE("Unlocked src and dst\n");
5743
5744         } else {
5745
5746             FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
5747             hr = WINED3DERR_INVALIDCALL;
5748          }
5749
5750     } else {
5751
5752         if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
5753
5754             int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
5755             unsigned int i;
5756
5757             /* Copy rect by rect */
5758             for (i = 0; i < cRects; ++i) {
5759                 CONST RECT*  r = &pSourceRectsArray[i];
5760                 CONST POINT* p = &pDestPointsArray[i];
5761                 int copyperline;
5762                 int j;
5763                 WINED3DLOCKED_RECT lrSrc;
5764                 WINED3DLOCKED_RECT lrDst;
5765                 RECT dest_rect;
5766
5767                 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
5768                 if (srcFormat == WINED3DFMT_DXT1) {
5769                     copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
5770                 } else {
5771                     copyperline = ((r->right - r->left) * bytesPerPixel);
5772                 }
5773
5774                 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
5775                 dest_rect.left  = p->x;
5776                 dest_rect.top   = p->y;
5777                 dest_rect.right = p->x + (r->right - r->left);
5778                 dest_rect.bottom= p->y + (r->bottom - r->top);
5779                 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
5780                 TRACE("Locked src and dst\n");
5781
5782                 /* Find where to start */
5783                 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
5784                     memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
5785                 }
5786                 IWineD3DSurface_UnlockRect(pSourceSurface);
5787                 IWineD3DSurface_UnlockRect(pDestinationSurface);
5788                 TRACE("Unlocked src and dst\n");
5789             }
5790         } else {
5791             FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
5792             hr = WINED3DERR_INVALIDCALL;
5793         }
5794     }
5795
5796     return hr;
5797 }
5798
5799 /* Implementation details at http://developer.nvidia.com/attach/6494
5800 and
5801 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5802 hmm.. no longer supported use
5803 OpenGL evaluators or  tessellate surfaces within your application.
5804 */
5805
5806 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5807 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5808     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5809     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5810     FIXME("(%p) : Stub\n", This);
5811     return WINED3D_OK;
5812
5813 }
5814
5815 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5816 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5817     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5818     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5819     FIXME("(%p) : Stub\n", This);
5820     return WINED3D_OK;
5821 }
5822
5823 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5824     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5825     TRACE("(%p) Handle(%d)\n", This, Handle);
5826     FIXME("(%p) : Stub\n", This);
5827     return WINED3D_OK;
5828 }
5829
5830 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5831     /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5832     fill a surface with a block of color!  */
5833     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5834     /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5835     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5836     IWineD3DSwapChainImpl *container = NULL;
5837     BOOL isRenderTarget = FALSE;
5838     unsigned int width, height;
5839     unsigned int top, left;
5840     unsigned int u, v;
5841     DWORD       *data;
5842     TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5843
5844     if (surface->resource.pool != WINED3DPOOL_DEFAULT) {
5845         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT surface\n");
5846         return WINED3DERR_INVALIDCALL;
5847     }
5848
5849     /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5850     if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5851         if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
5852             /* TODO: make sure we set everything back to the way it was, and context management!
5853                 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5854                 vcheckGLcall("glIntegerv");
5855                 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5856                 vcheckGLcall("glIntegerv");
5857             */
5858             TRACE("Color fill to render targets may cause some graphics issues\n");
5859             if (pSurface == container->frontBuffer) {
5860                 glDrawBuffer(GL_FRONT);
5861             } else {
5862                 glDrawBuffer(GL_BACK);
5863             }
5864         } else {
5865             if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5866                 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5867             } else {
5868                 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5869             }
5870             if (container != NULL) {
5871                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5872             }
5873             /* we can use GL_STENCIL_INDEX etc...*/
5874             return WINED3D_OK;
5875         }
5876         if (container != NULL) {
5877             IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5878         }
5879         isRenderTarget = TRUE;
5880     }
5881     /* TODO: drawing to GL_FRONT and GL_BACK */
5882     /* TODO: see if things can be speeded up by using the correct
5883      * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5884     if (pRect == NULL) {
5885         top    = 0;
5886         left   = 0;
5887         width  = surface->currentDesc.Width;
5888         height = surface->currentDesc.Height;
5889     } else {
5890         left   = pRect->x1;
5891         top    = pRect->y1;
5892         width  = pRect->x2 - left;
5893         height = pRect->y2 - top;
5894     }
5895
5896     data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5897     /* Create a 'line' of color color, in the correct format for the surface */
5898     for (u = 0 ; u < width ; u ++) {
5899             data[u] = color;
5900     }
5901
5902     ENTER_GL();
5903     if (isRenderTarget == FALSE) {
5904         glDescriptor *glDesc;
5905         IWineD3DSurface_PreLoad(pSurface);
5906
5907         /* draw a block of the coloured line on the sufrace */
5908         IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5909         for (v = 0 ; v< height;v++) {
5910             glTexSubImage2D(glDesc->target
5911                             ,glDesc->level /* level */
5912                             ,left
5913                             ,top + v
5914                             ,width
5915                             ,1 /* height */
5916                             ,GL_RGBA
5917                             ,GL_UNSIGNED_BYTE
5918                             ,data
5919                             );
5920         }
5921         checkGLcall("glTexSubImage2D");
5922         /* clean up */
5923         glDisable(glDesc->target);
5924     } else {
5925         /** FIXME: Using GLClear may be faster **/
5926         glRasterPos2i(left, top);
5927         glPixelZoom((float)width ,(float)height);
5928         glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5929         checkGLcall("glDrawPixels");
5930     }
5931     HeapFree(GetProcessHeap(), 0, data);
5932     LEAVE_GL();
5933     return WINED3D_OK;
5934
5935 }
5936
5937 /* rendertarget and deptth stencil functions */
5938 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5939     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5940
5941     /* FIXME: Implelent RenderTargetIndex >0 */
5942     if(RenderTargetIndex > 0)
5943         FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5944
5945     *ppRenderTarget = This->renderTarget;
5946     TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5947     /* Note inc ref on returned surface */
5948     if(*ppRenderTarget != NULL)
5949         IWineD3DSurface_AddRef(*ppRenderTarget);
5950     return WINED3D_OK;
5951 }
5952
5953 HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5954     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5955     *ppZStencilSurface = This->depthStencilBuffer;
5956     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5957
5958     if(*ppZStencilSurface != NULL) {
5959         /* Note inc ref on returned surface */
5960         IWineD3DSurface_AddRef(*ppZStencilSurface);
5961     }
5962     return WINED3D_OK;
5963 }
5964
5965 /* internal static helper functions */
5966 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5967                                                 IWineD3DSurface *RenderSurface);
5968
5969 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5970     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5971     HRESULT  hr = WINED3D_OK;
5972     WINED3DVIEWPORT viewport;
5973
5974     TRACE("(%p) Swapping rendertarget\n",This);
5975     if (RenderTargetIndex > 0) {
5976         FIXME("(%p) Render targets other than the first are not supported\n",This);
5977         RenderTargetIndex = 0;
5978     }
5979
5980     /* MSDN says that null disables the render target
5981     but a device must always be associated with a render target
5982     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5983
5984     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5985     for more details
5986     */
5987     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5988         FIXME("Trying to set render target 0 to NULL\n");
5989         return WINED3DERR_INVALIDCALL;
5990     }
5991     /* TODO: replace Impl* usage with interface usage */
5992     if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5993         FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
5994         return WINED3DERR_INVALIDCALL;
5995     }
5996     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5997      *        builds, but I think wine counts as a 'debug' build for now.
5998       ******************************/
5999     /* If we are trying to set what we already have, don't bother */
6000     if (pRenderTarget == This->renderTarget) {
6001         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6002     } else {
6003         /* Otherwise, set the render target up */
6004
6005         if (FALSE == This->sceneEnded) {
6006             IWineD3DDevice_EndScene(iface);
6007         }
6008         TRACE("clearing renderer\n");
6009         /* IWineD3DDeviceImpl_CleanRender(iface); */
6010         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6011         depending on the renter target implementation being used.
6012         A shared context implementation will share all buffers between all rendertargets (including swapchains),
6013         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6014         stencil buffer and incure an extra memory overhead */
6015         hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6016     }
6017
6018     if (SUCCEEDED(hr)) {
6019         /* Finally, reset the viewport as the MSDN states. */
6020         /* TODO: Replace impl usage */
6021         viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6022         viewport.Width  = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6023         viewport.X      = 0;
6024         viewport.Y      = 0;
6025         viewport.MaxZ   = 1.0f;
6026         viewport.MinZ   = 0.0f;
6027         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6028     } else {
6029         FIXME("Unknown error setting the render target\n");
6030     }
6031     This->sceneEnded = FALSE;
6032     return hr;
6033 }
6034
6035 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6036     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6037     HRESULT  hr = WINED3D_OK;
6038     IWineD3DSurface *tmp;
6039
6040     TRACE("(%p) Swapping z-buffer\n",This);
6041
6042     if (pNewZStencil == This->stencilBufferTarget) {
6043         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6044     } else {
6045         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6046         * depending on the renter target implementation being used.
6047         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6048         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6049         * stencil buffer and incure an extra memory overhead
6050          ******************************************************/
6051
6052
6053         tmp = This->stencilBufferTarget;
6054         This->stencilBufferTarget = pNewZStencil;
6055         /* should we be calling the parent or the wined3d surface? */
6056         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6057         if (NULL != tmp) IWineD3DSurface_Release(tmp);
6058         hr = WINED3D_OK;
6059         /** TODO: glEnable/glDisable on depth/stencil    depending on
6060          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
6061           **********************************************************/
6062     }
6063
6064     return hr;
6065 }
6066
6067
6068 #ifdef GL_VERSION_1_3
6069 /* Internal functions not in DirectX */
6070  /** TODO: move this off to the opengl context manager
6071  *(the swapchain doesn't need to know anything about offscreen rendering!)
6072   ****************************************************/
6073
6074 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6075 {
6076     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6077
6078     TRACE("(%p), %p\n", This, swapchain);
6079
6080     if (swapchain->win != swapchain->drawable) {
6081         /* Set everything back the way it ws */
6082         swapchain->render_ctx = swapchain->glCtx;
6083         swapchain->drawable   = swapchain->win;
6084     }
6085     return WINED3D_OK;
6086 }
6087
6088 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6089 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6090     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6091     int i;
6092     unsigned int width;
6093     unsigned int height;
6094     WINED3DFORMAT format;
6095     WINED3DSURFACE_DESC surfaceDesc;
6096     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6097     surfaceDesc.Width  = &width;
6098     surfaceDesc.Height = &height;
6099     surfaceDesc.Format = &format;
6100     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6101     *context = NULL;
6102     /* I need a get width/height function (and should do something with the format) */
6103     for (i = 0; i < CONTEXT_CACHE; ++i) {
6104         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6105         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6106         the pSurface can be set to 0 allowing it to be reused from cache **/
6107         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6108           && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6109             *context = &This->contextCache[i];
6110             break;
6111         }
6112         if (This->contextCache[i].Width == 0) {
6113             This->contextCache[i].pSurface = pSurface;
6114             This->contextCache[i].Width    = width;
6115             This->contextCache[i].Height   = height;
6116             *context = &This->contextCache[i];
6117             break;
6118         }
6119     }
6120     if (i == CONTEXT_CACHE) {
6121         int minUsage = 0x7FFFFFFF; /* MAX_INT */
6122         glContext *dropContext = 0;
6123         for (i = 0; i < CONTEXT_CACHE; i++) {
6124             if (This->contextCache[i].usedcount < minUsage) {
6125                 dropContext = &This->contextCache[i];
6126                 minUsage = This->contextCache[i].usedcount;
6127             }
6128         }
6129         /* clean up the context (this doesn't work for ATI at the moment */
6130 #if 0
6131         glXDestroyContext(swapchain->display, dropContext->context);
6132         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6133 #endif
6134         FIXME("Leak\n");
6135         dropContext->Width = 0;
6136         dropContext->pSurface = pSurface;
6137         *context = dropContext;
6138     } else {
6139         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6140           for (i = 0; i < CONTEXT_CACHE; i++) {
6141              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6142           }
6143         }
6144     }
6145     if (*context != NULL)
6146         return WINED3D_OK;
6147     else
6148         return E_OUTOFMEMORY;
6149 }
6150 #endif
6151
6152 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6153 * the functionality needs splitting up so that we don't do more than we should do.
6154 * this only seems to impact performance a little.
6155  ******************************/
6156 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6157                                                IWineD3DSurface *RenderSurface) {
6158     HRESULT ret =  WINED3DERR_INVALIDCALL;
6159
6160     /**
6161     * Currently only active for GLX >= 1.3
6162     * for others versions we'll have to use GLXPixmaps
6163     *
6164     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6165     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6166     * so only check OpenGL version
6167     * ..........................
6168     * I don't believe that it is a problem with NVidia headers,
6169     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6170     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6171     * ATI Note:
6172     * Your application will report GLX version 1.2 on glXQueryVersion.
6173     * However, it is safe to call the GLX 1.3 functions as described below.
6174     */
6175 #if defined(GL_VERSION_1_3)
6176
6177     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6178     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6179     IWineD3DSurface *tmp;
6180     /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6181     GLXFBConfig* cfgs = NULL;
6182     int nCfgs = 0;
6183     int attribs[256];
6184     int nAttribs = 0;
6185     IWineD3DSwapChain     *currentSwapchain;
6186     IWineD3DSwapChainImpl *swapchain;
6187     /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6188     * but switch them off if the StencilSurface is set to NULL
6189     ** *********************************************************/
6190     D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6191     D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6192
6193     /**TODO:
6194         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6195         it StencilSurface != NULL && zBufferTarget == NULL switch it on
6196     */
6197
6198 #define PUSH1(att)        attribs[nAttribs++] = (att);
6199 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6200
6201     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6202
6203     /** TODO: remove the reff to Impl (context manager should fix this!) **/
6204     IWineD3DSwapChainImpl *impSwapChain;
6205     IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6206     if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6207         ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6208     }
6209
6210     ENTER_GL();
6211
6212     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6213     PUSH2(GLX_X_RENDERABLE,  TRUE);
6214     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
6215     TRACE("calling makeglcfg\n");
6216     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6217     PUSH1(None);
6218
6219     TRACE("calling chooseFGConfig\n");
6220     cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6221                                                      attribs, &nCfgs);
6222
6223     if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6224         /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6225            why we failed and only show this message once! */
6226         MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
6227         nAttribs = 0;
6228         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6229        /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
6230         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
6231         PUSH2(GLX_DOUBLEBUFFER, FALSE);
6232         TRACE("calling makeglcfg\n");
6233         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6234         PUSH1(None);
6235         cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6236                                                         attribs, &nCfgs);
6237     }
6238
6239     if (NULL != cfgs) {
6240 #ifdef EXTRA_TRACES
6241         int i;
6242         for (i = 0; i < nCfgs; ++i) {
6243             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6244             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6245             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6246         }
6247
6248         if (NULL != This->renderTarget) {
6249             glFlush();
6250             vcheckGLcall("glFlush");
6251             /** This is only useful if the old render target was a swapchain,
6252             * we need to supercede this with a function that displays
6253             * the current buffer on the screen. This is easy to do in glx1.3 but
6254             * we need to do copy-write pixels in glx 1.2.
6255             ************************************************/
6256             glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6257
6258             printf("Hit Enter to get next frame ...\n");
6259             getchar();
6260         }
6261 #endif
6262     }
6263
6264     if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != WINED3D_OK) {
6265         /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6266         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
6267     }
6268
6269     /**
6270     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6271     *  renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6272      **********************************************************************/
6273     if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6274         /* We also need to make sure that the lights &co are also in the context of the swapchains */
6275         /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6276         TRACE("making swapchain active\n");
6277         if (RenderSurface != This->renderTarget) {
6278             if (RenderSurface ==  swapchain->backBuffer) {
6279             } else {
6280                 /* This could be flagged so that some operations work directly with the front buffer */
6281                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
6282             }
6283             if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6284             == False) {
6285                 TRACE("Error in setting current context: context %p drawable %ld !\n",
6286                        impSwapChain->glCtx, impSwapChain->win);
6287             }
6288
6289             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6290         }
6291         checkGLcall("glXMakeContextCurrent");
6292
6293         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6294     }
6295     else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6296
6297         /** ********************************************************************
6298         * This is a quickly hacked out implementation of offscreen textures.
6299         * It will work in most cases but there may be problems if the client
6300         * modifies the texture directly, or expects the contents of the rendertarget
6301         * to be persistent.
6302         *
6303         * There are some real speed vs compatibility issues here:
6304         *    we should really use a new context for every texture, but that eats ram.
6305         *    we should also be restoring the texture to the pbuffer but that eats CPU
6306         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6307         *    but if this means reusing the display backbuffer then we need to make sure that
6308         *    states are correctly preserved.
6309         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6310         * and gain a good performance increase at the cost of compatibility.
6311         * I would suggest that, when this is the case, a user configurable flag be made
6312         * available, allowing the user to choose the best emulated experience for them.
6313          *********************************************************************/
6314
6315         XVisualInfo *visinfo;
6316         glContext   *newContext;
6317
6318         /* Here were using a shared context model */
6319         if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6320             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6321         }
6322
6323         /* If the context doesn't exist then create a new one */
6324         /* TODO: This should really be part of findGlContext */
6325         if (NULL == newContext->context) {
6326
6327             TRACE("making new buffer\n");
6328             nAttribs = 0;
6329             PUSH2(GLX_PBUFFER_WIDTH,  newContext->Width);
6330             PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6331             PUSH1(None);
6332
6333             newContext->drawable  = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6334
6335             /** ****************************************
6336             *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6337             *they note:
6338             *   In future releases, we may provide the calls glXCreateNewContext,
6339             *   glXQueryDrawable and glXMakeContextCurrent.
6340             *    so until then we have to use glXGetVisualFromFBConfig &co..
6341             ********************************************/
6342
6343
6344             visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6345             if (!visinfo) {
6346                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6347             } else {
6348                 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx,  GL_TRUE);
6349                 XFree(visinfo);
6350             }
6351         }
6352         if (NULL == newContext || NULL == newContext->context) {
6353             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6354         } else {
6355             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6356             if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6357                 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6358             }
6359
6360             /* Clean up the old context */
6361             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6362             /* Set the current context of the swapchain to the new context */
6363             impSwapChain->drawable   = newContext->drawable;
6364             impSwapChain->render_ctx = newContext->context;
6365         }
6366     }
6367
6368 #if 1 /* Apply the stateblock to the new context
6369 FIXME: This is a bit of a hack, each context should know it's own state,
6370 the directX current directX state should then be applied to the context */
6371     {
6372         BOOL oldRecording;
6373         IWineD3DStateBlockImpl *oldUpdateStateBlock;
6374         oldUpdateStateBlock = This->updateStateBlock;
6375         oldRecording= This->isRecordingState;
6376         This->isRecordingState = FALSE;
6377         This->updateStateBlock = This->stateBlock;
6378         IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6379
6380         This->isRecordingState = oldRecording;
6381         This->updateStateBlock = oldUpdateStateBlock;
6382     }
6383 #endif
6384
6385
6386     /* clean up the current rendertargets swapchain (if it belonged to one) */
6387     if (currentSwapchain != NULL) {
6388         IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6389     }
6390
6391     /* Were done with the opengl context management, setup the rendertargets */
6392
6393     tmp = This->renderTarget;
6394     This->renderTarget = RenderSurface;
6395     IWineD3DSurface_AddRef(This->renderTarget);
6396     IWineD3DSurface_Release(tmp);
6397
6398
6399
6400     {
6401         DWORD value;
6402         /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6403         /* Check that the container is not a swapchain member */
6404
6405         IWineD3DSwapChain *tmpSwapChain;
6406         if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6407             This->renderUpsideDown = TRUE;
6408         }else{
6409             This->renderUpsideDown = FALSE;
6410             IWineD3DSwapChain_Release(tmpSwapChain);
6411         }
6412         /* Force updating the cull mode */
6413         TRACE("setting render state\n");
6414         IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6415         IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6416
6417         /* Force updating projection matrix */
6418         This->last_was_rhw = FALSE;
6419         This->proj_valid = FALSE;
6420     }
6421
6422     ret = WINED3D_OK;
6423
6424     if (cfgs != NULL) {
6425         XFree(cfgs);
6426     } else {
6427         ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6428             debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6429     }
6430
6431 #undef PUSH1
6432 #undef PUSH2
6433     if ( NULL != impSwapChain) {
6434         IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6435     }
6436     LEAVE_GL();
6437
6438 #endif
6439     return ret;
6440 }
6441
6442 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6443                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6444     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6445     /* TODO: the use of Impl is deprecated. */
6446     /* some basic validation checks */
6447     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6448
6449     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6450
6451     if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6452       ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6453       return WINED3DERR_INVALIDCALL;
6454     }
6455     if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6456       ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6457       return WINED3DERR_INVALIDCALL;
6458     }
6459     /* TODO: make the cursor 'real' */
6460
6461     This->xHotSpot = XHotSpot;
6462     This->yHotSpot = YHotSpot;
6463
6464     return WINED3D_OK;
6465 }
6466
6467 void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6468     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6469     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6470
6471     This->xScreenSpace = XScreenSpace;
6472     This->yScreenSpace = YScreenSpace;
6473
6474     return;
6475
6476 }
6477
6478 BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6479     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6480     TRACE("(%p) : visible(%d)\n", This, bShow);
6481
6482     This->bCursorVisible = bShow;
6483
6484     return WINED3D_OK;
6485 }
6486
6487 HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6488     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6489     TRACE("(%p) : state (%lu)\n", This, This->state);
6490     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6491     switch (This->state) {
6492     case WINED3D_OK:
6493         return WINED3D_OK;
6494     case WINED3DERR_DEVICELOST:
6495         {
6496             ResourceList *resourceList  = This->resources;
6497             while (NULL != resourceList) {
6498                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6499                 return WINED3DERR_DEVICENOTRESET;
6500                 resourceList = resourceList->next;
6501             }
6502             return WINED3DERR_DEVICELOST;
6503         }
6504     case WINED3DERR_DRIVERINTERNALERROR:
6505         return WINED3DERR_DRIVERINTERNALERROR;
6506     }
6507
6508     /* Unknown state */
6509     return WINED3DERR_DRIVERINTERNALERROR;
6510 }
6511
6512
6513 HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6514     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6515     /** FIXME: Resource tracking needs to be done,
6516     * The closes we can do to this is set the priorities of all managed textures low
6517     * and then reset them.
6518      ***********************************************************/
6519     FIXME("(%p) : stub\n", This);
6520     return WINED3D_OK;
6521 }
6522
6523 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6524     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6525     /** FIXME: Resource trascking needs to be done.
6526     * in effect this pulls all non only default
6527     * textures out of video memory and deletes all glTextures (glDeleteTextures)
6528     * and should clear down the context and set it up according to pPresentationParameters
6529      ***********************************************************/
6530     FIXME("(%p) : stub\n", This);
6531     return WINED3D_OK;
6532 }
6533
6534 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6535     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6536     /** FIXME: always true at the moment **/
6537     if(bEnableDialogs == FALSE) {
6538         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6539     }
6540     return WINED3D_OK;
6541 }
6542
6543
6544 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6545     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6546     TRACE("(%p) : pParameters %p\n", This, pParameters);
6547
6548     *pParameters = This->createParms;
6549     return WINED3D_OK;
6550 }
6551
6552 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6553     IWineD3DSwapChain *swapchain;
6554     HRESULT hrc = WINED3D_OK;
6555
6556     TRACE("Relaying  to swapchain\n");
6557
6558     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6559         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6560         IWineD3DSwapChain_Release(swapchain);
6561     }
6562     return;
6563 }
6564
6565 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6566     IWineD3DSwapChain *swapchain;
6567     HRESULT hrc = WINED3D_OK;
6568
6569     TRACE("Relaying  to swapchain\n");
6570
6571     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6572         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6573         IWineD3DSwapChain_Release(swapchain);
6574     }
6575     return;
6576 }
6577
6578
6579 /** ********************************************************
6580 *   Notification functions
6581 ** ********************************************************/
6582 /** This function must be called in the release of a resource when ref == 0,
6583 * the contents of resource must still be correct,
6584 * any handels to other resource held by the caller must be closed
6585 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6586  *****************************************************/
6587 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6588     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6589     ResourceList* resourceList;
6590
6591     TRACE("(%p) : resource %p\n", This, resource);
6592 #if 0
6593     EnterCriticalSection(&resourceStoreCriticalSection);
6594 #endif
6595     /* add a new texture to the frot of the linked list */
6596     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6597     resourceList->resource = resource;
6598
6599     /* Get the old head */
6600     resourceList->next = This->resources;
6601
6602     This->resources = resourceList;
6603     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6604
6605 #if 0
6606     LeaveCriticalSection(&resourceStoreCriticalSection);
6607 #endif
6608     return;
6609 }
6610
6611 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6612     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6613     ResourceList* resourceList = NULL;
6614     ResourceList* previousResourceList = NULL;
6615     
6616     TRACE("(%p) : resource %p\n", This, resource);
6617
6618 #if 0
6619     EnterCriticalSection(&resourceStoreCriticalSection);
6620 #endif
6621     resourceList = This->resources;
6622
6623     while (resourceList != NULL) {
6624         if(resourceList->resource == resource) break;
6625         previousResourceList = resourceList;
6626         resourceList = resourceList->next;
6627     }
6628
6629     if (resourceList == NULL) {
6630         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6631 #if 0
6632         LeaveCriticalSection(&resourceStoreCriticalSection);
6633 #endif
6634         return;
6635     } else {
6636             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6637     }
6638     /* make sure we don't leave a hole in the list */
6639     if (previousResourceList != NULL) {
6640         previousResourceList->next = resourceList->next;
6641     } else {
6642         This->resources = resourceList->next;
6643     }
6644
6645 #if 0
6646     LeaveCriticalSection(&resourceStoreCriticalSection);
6647 #endif
6648     return;
6649 }
6650
6651
6652 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6653     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6654     int counter;
6655
6656     TRACE("(%p) : resource %p\n", This, resource);
6657     switch(IWineD3DResource_GetType(resource)){
6658         case WINED3DRTYPE_SURFACE:
6659         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6660         break;
6661         case WINED3DRTYPE_TEXTURE:
6662         case WINED3DRTYPE_CUBETEXTURE:
6663         case WINED3DRTYPE_VOLUMETEXTURE:
6664                 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6665                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6666                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6667                         This->stateBlock->textures[counter] = NULL;
6668                     }
6669                     if (This->updateStateBlock != This->stateBlock ){
6670                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6671                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6672                             This->updateStateBlock->textures[counter] = NULL;
6673                         }
6674                     }
6675                 }
6676         break;
6677         case WINED3DRTYPE_VOLUME:
6678         /* TODO: nothing really? */
6679         break;
6680         case WINED3DRTYPE_VERTEXBUFFER:
6681         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6682         {
6683             int streamNumber;
6684             TRACE("Cleaning up stream pointers\n");
6685
6686             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6687                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6688                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6689                 */
6690                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6691                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6692                         FIXME("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
6693                         This->updateStateBlock->streamSource[streamNumber] = 0;
6694                         /* Set changed flag? */
6695                     }
6696                 }
6697                 if (This->stateBlock != NULL ) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
6698                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6699                         TRACE("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
6700                         This->stateBlock->streamSource[streamNumber] = 0;
6701                     }
6702                 }
6703 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6704                  else { /* This shouldn't happen */
6705                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6706                 }
6707 #endif
6708
6709             }
6710         }
6711         break;
6712         case WINED3DRTYPE_INDEXBUFFER:
6713         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6714         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6715             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6716                 This->updateStateBlock->pIndexData =  NULL;
6717             }
6718         }
6719         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6720             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6721                 This->stateBlock->pIndexData =  NULL;
6722             }
6723         }
6724
6725         break;
6726         default:
6727         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6728         break;
6729     }
6730
6731
6732     /* Remove the resoruce from the resourceStore */
6733     IWineD3DDeviceImpl_RemoveResource(iface, resource);
6734
6735     TRACE("Resource released\n");
6736
6737 }
6738
6739
6740 /** This function is to be called by the swapchain when it is released and it's ref = 0
6741  *****************************************************/
6742 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6743     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6744     SwapChainList **nextSwapchain;
6745     nextSwapchain = &This->swapchains;
6746
6747     /* Check to see if the swapchian is being used as the render target */
6748     if (This->renderTarget != NULL) {
6749         IWineD3DSurface *swapchainBackBuffer;
6750
6751         IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6752         if (This->renderTarget == swapchainBackBuffer) {
6753             /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6754             FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6755         }
6756     }
6757
6758     /* Go through the swapchain list and try to find the swapchain being released */
6759     while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6760         nextSwapchain = &(*nextSwapchain)->next;
6761     }
6762
6763     /* Check to see if we found the swapchain */
6764     if (NULL != *nextSwapchain) {
6765         /* We found the swapchain so remove it from the list */
6766         TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6767         HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6768         *nextSwapchain = (*nextSwapchain)->next;
6769     } else {
6770         /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6771         FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6772     }
6773
6774     TRACE("swapchain (%p) released\n", swapChain);
6775     return;
6776 }
6777
6778 /**********************************************************
6779  * IWineD3DDevice VTbl follows
6780  **********************************************************/
6781
6782 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6783 {
6784     /*** IUnknown methods ***/
6785     IWineD3DDeviceImpl_QueryInterface,
6786     IWineD3DDeviceImpl_AddRef,
6787     IWineD3DDeviceImpl_Release,
6788     /*** IWineD3DDevice methods ***/
6789     IWineD3DDeviceImpl_GetParent,
6790     /*** Creation methods**/
6791     IWineD3DDeviceImpl_CreateVertexBuffer,
6792     IWineD3DDeviceImpl_CreateIndexBuffer,
6793     IWineD3DDeviceImpl_CreateStateBlock,
6794     IWineD3DDeviceImpl_CreateSurface,
6795     IWineD3DDeviceImpl_CreateTexture,
6796     IWineD3DDeviceImpl_CreateVolumeTexture,
6797     IWineD3DDeviceImpl_CreateVolume,
6798     IWineD3DDeviceImpl_CreateCubeTexture,
6799     IWineD3DDeviceImpl_CreateQuery,
6800     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6801     IWineD3DDeviceImpl_CreateVertexDeclaration,
6802     IWineD3DDeviceImpl_CreateVertexShader,
6803     IWineD3DDeviceImpl_CreatePixelShader,
6804     /*** Odd functions **/
6805     IWineD3DDeviceImpl_Init3D,
6806     IWineD3DDeviceImpl_Uninit3D,
6807     IWineD3DDeviceImpl_EvictManagedResources,
6808     IWineD3DDeviceImpl_GetAvailableTextureMem,
6809     IWineD3DDeviceImpl_GetBackBuffer,
6810     IWineD3DDeviceImpl_GetCreationParameters,
6811     IWineD3DDeviceImpl_GetDeviceCaps,
6812     IWineD3DDeviceImpl_GetDirect3D,
6813     IWineD3DDeviceImpl_GetDisplayMode,
6814     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6815     IWineD3DDeviceImpl_GetRasterStatus,
6816     IWineD3DDeviceImpl_GetSwapChain,
6817     IWineD3DDeviceImpl_Reset,
6818     IWineD3DDeviceImpl_SetDialogBoxMode,
6819     IWineD3DDeviceImpl_SetCursorProperties,
6820     IWineD3DDeviceImpl_SetCursorPosition,
6821     IWineD3DDeviceImpl_ShowCursor,
6822     IWineD3DDeviceImpl_TestCooperativeLevel,
6823     /*** Getters and setters **/
6824     IWineD3DDeviceImpl_SetClipPlane,
6825     IWineD3DDeviceImpl_GetClipPlane,
6826     IWineD3DDeviceImpl_SetClipStatus,
6827     IWineD3DDeviceImpl_GetClipStatus,
6828     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6829     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6830     IWineD3DDeviceImpl_SetDepthStencilSurface,
6831     IWineD3DDeviceImpl_GetDepthStencilSurface,
6832     IWineD3DDeviceImpl_SetFVF,
6833     IWineD3DDeviceImpl_GetFVF,
6834     IWineD3DDeviceImpl_SetGammaRamp,
6835     IWineD3DDeviceImpl_GetGammaRamp,
6836     IWineD3DDeviceImpl_SetIndices,
6837     IWineD3DDeviceImpl_GetIndices,
6838     IWineD3DDeviceImpl_SetLight,
6839     IWineD3DDeviceImpl_GetLight,
6840     IWineD3DDeviceImpl_SetLightEnable,
6841     IWineD3DDeviceImpl_GetLightEnable,
6842     IWineD3DDeviceImpl_SetMaterial,
6843     IWineD3DDeviceImpl_GetMaterial,
6844     IWineD3DDeviceImpl_SetNPatchMode,
6845     IWineD3DDeviceImpl_GetNPatchMode,
6846     IWineD3DDeviceImpl_SetPaletteEntries,
6847     IWineD3DDeviceImpl_GetPaletteEntries,
6848     IWineD3DDeviceImpl_SetPixelShader,
6849     IWineD3DDeviceImpl_GetPixelShader,
6850     IWineD3DDeviceImpl_SetPixelShaderConstant,
6851     IWineD3DDeviceImpl_GetPixelShaderConstant,
6852     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6853     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6854     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6855     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6856     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6857     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6858     IWineD3DDeviceImpl_SetPixelShaderConstantN,
6859     IWineD3DDeviceImpl_SetRenderState,
6860     IWineD3DDeviceImpl_GetRenderState,
6861     IWineD3DDeviceImpl_SetRenderTarget,
6862     IWineD3DDeviceImpl_GetRenderTarget,
6863     IWineD3DDeviceImpl_SetSamplerState,
6864     IWineD3DDeviceImpl_GetSamplerState,
6865     IWineD3DDeviceImpl_SetScissorRect,
6866     IWineD3DDeviceImpl_GetScissorRect,
6867     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6868     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6869     IWineD3DDeviceImpl_SetStreamSource,
6870     IWineD3DDeviceImpl_GetStreamSource,
6871     IWineD3DDeviceImpl_SetStreamSourceFreq,
6872     IWineD3DDeviceImpl_GetStreamSourceFreq,
6873     IWineD3DDeviceImpl_SetTexture,
6874     IWineD3DDeviceImpl_GetTexture,
6875     IWineD3DDeviceImpl_SetTextureStageState,
6876     IWineD3DDeviceImpl_GetTextureStageState,
6877     IWineD3DDeviceImpl_SetTransform,
6878     IWineD3DDeviceImpl_GetTransform,
6879     IWineD3DDeviceImpl_SetVertexDeclaration,
6880     IWineD3DDeviceImpl_GetVertexDeclaration,
6881     IWineD3DDeviceImpl_SetVertexShader,
6882     IWineD3DDeviceImpl_GetVertexShader,
6883     IWineD3DDeviceImpl_SetVertexShaderConstant,
6884     IWineD3DDeviceImpl_GetVertexShaderConstant,
6885     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6886     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6887     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6888     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6889     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6890     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6891     IWineD3DDeviceImpl_SetVertexShaderConstantN,
6892     IWineD3DDeviceImpl_SetViewport,
6893     IWineD3DDeviceImpl_GetViewport,
6894     IWineD3DDeviceImpl_MultiplyTransform,
6895     IWineD3DDeviceImpl_ValidateDevice,
6896     IWineD3DDeviceImpl_ProcessVertices,
6897     /*** State block ***/
6898     IWineD3DDeviceImpl_BeginStateBlock,
6899     IWineD3DDeviceImpl_EndStateBlock,
6900     /*** Scene management ***/
6901     IWineD3DDeviceImpl_BeginScene,
6902     IWineD3DDeviceImpl_EndScene,
6903     IWineD3DDeviceImpl_Present,
6904     IWineD3DDeviceImpl_Clear,
6905     /*** Drawing ***/
6906     IWineD3DDeviceImpl_DrawPrimitive,
6907     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6908     IWineD3DDeviceImpl_DrawPrimitiveUP,
6909     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6910     IWineD3DDeviceImpl_DrawRectPatch,
6911     IWineD3DDeviceImpl_DrawTriPatch,
6912     IWineD3DDeviceImpl_DeletePatch,
6913     IWineD3DDeviceImpl_ColorFill,
6914     IWineD3DDeviceImpl_UpdateTexture,
6915     IWineD3DDeviceImpl_UpdateSurface,
6916     IWineD3DDeviceImpl_CopyRects,
6917     IWineD3DDeviceImpl_StretchRect,
6918     IWineD3DDeviceImpl_GetRenderTargetData,
6919     IWineD3DDeviceImpl_GetFrontBufferData,
6920     /*** Internal use IWineD3DDevice methods ***/
6921     IWineD3DDeviceImpl_SetupTextureStates,
6922     /*** object tracking ***/
6923     IWineD3DDeviceImpl_SwapChainReleased,
6924     IWineD3DDeviceImpl_ResourceReleased
6925 };
6926
6927
6928 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6929     WINED3DRS_ALPHABLENDENABLE   ,
6930     WINED3DRS_ALPHAFUNC          ,
6931     WINED3DRS_ALPHAREF           ,
6932     WINED3DRS_ALPHATESTENABLE    ,
6933     WINED3DRS_BLENDOP            ,
6934     WINED3DRS_COLORWRITEENABLE   ,
6935     WINED3DRS_DESTBLEND          ,
6936     WINED3DRS_DITHERENABLE       ,
6937     WINED3DRS_FILLMODE           ,
6938     WINED3DRS_FOGDENSITY         ,
6939     WINED3DRS_FOGEND             ,
6940     WINED3DRS_FOGSTART           ,
6941     WINED3DRS_LASTPIXEL          ,
6942     WINED3DRS_SHADEMODE          ,
6943     WINED3DRS_SRCBLEND           ,
6944     WINED3DRS_STENCILENABLE      ,
6945     WINED3DRS_STENCILFAIL        ,
6946     WINED3DRS_STENCILFUNC        ,
6947     WINED3DRS_STENCILMASK        ,
6948     WINED3DRS_STENCILPASS        ,
6949     WINED3DRS_STENCILREF         ,
6950     WINED3DRS_STENCILWRITEMASK   ,
6951     WINED3DRS_STENCILZFAIL       ,
6952     WINED3DRS_TEXTUREFACTOR      ,
6953     WINED3DRS_WRAP0              ,
6954     WINED3DRS_WRAP1              ,
6955     WINED3DRS_WRAP2              ,
6956     WINED3DRS_WRAP3              ,
6957     WINED3DRS_WRAP4              ,
6958     WINED3DRS_WRAP5              ,
6959     WINED3DRS_WRAP6              ,
6960     WINED3DRS_WRAP7              ,
6961     WINED3DRS_ZENABLE            ,
6962     WINED3DRS_ZFUNC              ,
6963     WINED3DRS_ZWRITEENABLE
6964 };
6965
6966 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6967     WINED3DTSS_ADDRESSW              ,
6968     WINED3DTSS_ALPHAARG0             ,
6969     WINED3DTSS_ALPHAARG1             ,
6970     WINED3DTSS_ALPHAARG2             ,
6971     WINED3DTSS_ALPHAOP               ,
6972     WINED3DTSS_BUMPENVLOFFSET        ,
6973     WINED3DTSS_BUMPENVLSCALE         ,
6974     WINED3DTSS_BUMPENVMAT00          ,
6975     WINED3DTSS_BUMPENVMAT01          ,
6976     WINED3DTSS_BUMPENVMAT10          ,
6977     WINED3DTSS_BUMPENVMAT11          ,
6978     WINED3DTSS_COLORARG0             ,
6979     WINED3DTSS_COLORARG1             ,
6980     WINED3DTSS_COLORARG2             ,
6981     WINED3DTSS_COLOROP               ,
6982     WINED3DTSS_RESULTARG             ,
6983     WINED3DTSS_TEXCOORDINDEX         ,
6984     WINED3DTSS_TEXTURETRANSFORMFLAGS
6985 };
6986
6987 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6988     WINED3DSAMP_ADDRESSU         ,
6989     WINED3DSAMP_ADDRESSV         ,
6990     WINED3DSAMP_ADDRESSW         ,
6991     WINED3DSAMP_BORDERCOLOR      ,
6992     WINED3DSAMP_MAGFILTER        ,
6993     WINED3DSAMP_MINFILTER        ,
6994     WINED3DSAMP_MIPFILTER        ,
6995     WINED3DSAMP_MIPMAPLODBIAS    ,
6996     WINED3DSAMP_MAXMIPLEVEL      ,
6997     WINED3DSAMP_MAXANISOTROPY    ,
6998     WINED3DSAMP_SRGBTEXTURE      ,
6999     WINED3DSAMP_ELEMENTINDEX
7000 };
7001
7002 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7003     WINED3DRS_AMBIENT                       ,
7004     WINED3DRS_AMBIENTMATERIALSOURCE         ,
7005     WINED3DRS_CLIPPING                      ,
7006     WINED3DRS_CLIPPLANEENABLE               ,
7007     WINED3DRS_COLORVERTEX                   ,
7008     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
7009     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
7010     WINED3DRS_FOGDENSITY                    ,
7011     WINED3DRS_FOGEND                        ,
7012     WINED3DRS_FOGSTART                      ,
7013     WINED3DRS_FOGTABLEMODE                  ,
7014     WINED3DRS_FOGVERTEXMODE                 ,
7015     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
7016     WINED3DRS_LIGHTING                      ,
7017     WINED3DRS_LOCALVIEWER                   ,
7018     WINED3DRS_MULTISAMPLEANTIALIAS          ,
7019     WINED3DRS_MULTISAMPLEMASK               ,
7020     WINED3DRS_NORMALIZENORMALS              ,
7021     WINED3DRS_PATCHEDGESTYLE                ,
7022     WINED3DRS_POINTSCALE_A                  ,
7023     WINED3DRS_POINTSCALE_B                  ,
7024     WINED3DRS_POINTSCALE_C                  ,
7025     WINED3DRS_POINTSCALEENABLE              ,
7026     WINED3DRS_POINTSIZE                     ,
7027     WINED3DRS_POINTSIZE_MAX                 ,
7028     WINED3DRS_POINTSIZE_MIN                 ,
7029     WINED3DRS_POINTSPRITEENABLE             ,
7030     WINED3DRS_RANGEFOGENABLE                ,
7031     WINED3DRS_SPECULARMATERIALSOURCE        ,
7032     WINED3DRS_TWEENFACTOR                   ,
7033     WINED3DRS_VERTEXBLEND
7034 };
7035
7036 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7037     WINED3DTSS_TEXCOORDINDEX         ,
7038     WINED3DTSS_TEXTURETRANSFORMFLAGS
7039 };
7040
7041 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7042     WINED3DSAMP_DMAPOFFSET
7043 };