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