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