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