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