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