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