wined3d: Share get_opcode.
[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 */, NULL);
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, NULL);
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 */, NULL);
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, NULL);
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 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5388
5389     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5390     return WINED3D_OK;
5391 }
5392  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5393 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
5394     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5395     HRESULT hr = WINED3D_OK;
5396     WINED3DRESOURCETYPE sourceType;
5397     WINED3DRESOURCETYPE destinationType;
5398     int i ,levels;
5399
5400     /* TODO: think about moving the code into IWineD3DBaseTexture  */
5401
5402     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5403
5404     /* verify that the source and destination textures aren't NULL */
5405     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5406         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5407              This, pSourceTexture, pDestinationTexture);
5408         hr = WINED3DERR_INVALIDCALL;
5409     }
5410
5411     if (pSourceTexture == pDestinationTexture) {
5412         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5413              This, pSourceTexture, pDestinationTexture);
5414         hr = WINED3DERR_INVALIDCALL;
5415     }
5416     /* Verify that the source and destination textures are the same type */
5417     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5418     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5419
5420     if (sourceType != destinationType) {
5421         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5422              This);
5423         hr = WINED3DERR_INVALIDCALL;
5424     }
5425
5426     /* check that both textures have the identical numbers of levels  */
5427     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5428         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5429         hr = WINED3DERR_INVALIDCALL;
5430     }
5431
5432     if (WINED3D_OK == hr) {
5433
5434         /* Make sure that the destination texture is loaded */
5435         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5436
5437         /* Update every surface level of the texture */
5438         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5439
5440         switch (sourceType) {
5441         case WINED3DRTYPE_TEXTURE:
5442             {
5443                 IWineD3DSurface *srcSurface;
5444                 IWineD3DSurface *destSurface;
5445
5446                 for (i = 0 ; i < levels ; ++i) {
5447                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
5448                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5449                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5450                     IWineD3DSurface_Release(srcSurface);
5451                     IWineD3DSurface_Release(destSurface);
5452                     if (WINED3D_OK != hr) {
5453                         WARN("(%p) : Call to update surface failed\n", This);
5454                         return hr;
5455                     }
5456                 }
5457             }
5458             break;
5459         case WINED3DRTYPE_CUBETEXTURE:
5460             {
5461                 IWineD3DSurface *srcSurface;
5462                 IWineD3DSurface *destSurface;
5463                 WINED3DCUBEMAP_FACES faceType;
5464
5465                 for (i = 0 ; i < levels ; ++i) {
5466                     /* Update each cube face */
5467                     for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5468                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
5469                         if (WINED3D_OK != hr) {
5470                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5471                         } else {
5472                             TRACE("Got srcSurface %p\n", srcSurface);
5473                         }
5474                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5475                         if (WINED3D_OK != hr) {
5476                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5477                         } else {
5478                             TRACE("Got desrSurface %p\n", destSurface);
5479                         }
5480                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5481                         IWineD3DSurface_Release(srcSurface);
5482                         IWineD3DSurface_Release(destSurface);
5483                         if (WINED3D_OK != hr) {
5484                             WARN("(%p) : Call to update surface failed\n", This);
5485                             return hr;
5486                         }
5487                     }
5488                 }
5489             }
5490             break;
5491 #if 0 /* TODO: Add support for volume textures */
5492         case WINED3DRTYPE_VOLUMETEXTURE:
5493             {
5494                 IWineD3DVolume  srcVolume  = NULL;
5495                 IWineD3DSurface destVolume = NULL;
5496
5497                 for (i = 0 ; i < levels ; ++i) {
5498                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5499                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5500                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5501                     IWineD3DVolume_Release(srcSurface);
5502                     IWineD3DVolume_Release(destSurface);
5503                     if (WINED3D_OK != hr) {
5504                         WARN("(%p) : Call to update volume failed\n", This);
5505                         return hr;
5506                     }
5507                 }
5508             }
5509             break;
5510 #endif
5511         default:
5512             FIXME("(%p) : Unsupported source and destination type\n", This);
5513             hr = WINED3DERR_INVALIDCALL;
5514         }
5515     }
5516
5517     return hr;
5518 }
5519
5520 HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5521                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5522                                                 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5523     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5524
5525     TRACE("(%p) : stub\n", This);
5526     return WINED3D_OK;
5527 }
5528 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5529     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5530     /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5531     *  NOTE It may be best to move the code into surface to occomplish this
5532     ****************************************/
5533
5534     WINED3DSURFACE_DESC surfaceDesc;
5535     unsigned int surfaceWidth, surfaceHeight;
5536     glDescriptor *targetGlDescription  = NULL;
5537     glDescriptor *surfaceGlDescription = NULL;
5538     IWineD3DSwapChainImpl *container = NULL;
5539     
5540     IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5541     IWineD3DSurface_GetGlDesc(pSurface,      &surfaceGlDescription);
5542     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5543
5544     surfaceDesc.Width  = &surfaceWidth;
5545     surfaceDesc.Height = &surfaceHeight;
5546     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5547    /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5548
5549     /* Ok, I may need to setup some kind of active swapchain reference on the device */
5550     IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5551     ENTER_GL();
5552     /* TODO: opengl Context switching for swapchains etc... */
5553     if (NULL != container  || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5554         if (NULL != container  && (pRenderTarget == container->backBuffer)) {
5555             glReadBuffer(GL_BACK);
5556             vcheckGLcall("glReadBuffer(GL_BACK)");
5557         } else if ((NULL != container  && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5558             glReadBuffer(GL_FRONT);
5559             vcheckGLcall("glReadBuffer(GL_FRONT)");
5560         } else if (pRenderTarget == This->depthStencilBuffer) {
5561             FIXME("Reading of depthstencil not yet supported\n");
5562         }
5563
5564         glReadPixels(surfaceGlDescription->target,
5565                     surfaceGlDescription->level,
5566                     surfaceWidth,
5567                     surfaceHeight,
5568                     surfaceGlDescription->glFormat,
5569                     surfaceGlDescription->glType,
5570                     (void *)IWineD3DSurface_GetData(pSurface));
5571         vcheckGLcall("glReadPixels(...)");
5572         if(NULL != container ){
5573             IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5574         }
5575     } else {
5576         IWineD3DBaseTexture *container;
5577         GLenum textureDimensions = GL_TEXTURE_2D;
5578
5579         if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5580             textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5581             IWineD3DBaseTexture_Release(container);
5582         }
5583         /* TODO: 2D -> Cube surface coppies etc.. */
5584         if (surfaceGlDescription->target != textureDimensions) {
5585             FIXME("(%p) : Texture dimension mismatch\n", This);
5586         }
5587         glEnable(textureDimensions);
5588         vcheckGLcall("glEnable(GL_TEXTURE_...)");
5589         /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5590         glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5591         vcheckGLcall("glBindTexture");
5592         glGetTexImage(surfaceGlDescription->target,
5593                         surfaceGlDescription->level,
5594                         surfaceGlDescription->glFormat,
5595                         surfaceGlDescription->glType,
5596                         (void *)IWineD3DSurface_GetData(pSurface));
5597         glDisable(textureDimensions);
5598         vcheckGLcall("glDisable(GL_TEXTURE_...)");
5599
5600     }
5601     LEAVE_GL();
5602     return WINED3D_OK;
5603 }
5604
5605 HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5606     IWineD3DSwapChain *swapChain;
5607     HRESULT hr;
5608     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5609     if(hr == WINED3D_OK) {
5610         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5611                 IWineD3DSwapChain_Release(swapChain);
5612     }
5613     return hr;
5614 }
5615
5616 HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5617     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5618     /* return a sensible default */
5619     *pNumPasses = 1;
5620     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5621     FIXME("(%p) : stub\n", This);
5622     return WINED3D_OK;
5623 }
5624
5625 HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5626     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5627     int j;
5628     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5629     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5630         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5631         return WINED3DERR_INVALIDCALL;
5632     }
5633     for (j = 0; j < 256; ++j) {
5634         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5635         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5636         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5637         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5638     }
5639     TRACE("(%p) : returning\n", This);
5640     return WINED3D_OK;
5641 }
5642
5643 HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5644     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5645     int j;
5646     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5647     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5648         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5649         return WINED3DERR_INVALIDCALL;
5650     }
5651     for (j = 0; j < 256; ++j) {
5652         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5653         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5654         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5655         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5656     }
5657     TRACE("(%p) : returning\n", This);
5658     return WINED3D_OK;
5659 }
5660
5661 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5662     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5663     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5664     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5665         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5666         return WINED3DERR_INVALIDCALL;
5667     }
5668     /*TODO: stateblocks */
5669     This->currentPalette = PaletteNumber;
5670     TRACE("(%p) : returning\n", This);
5671     return WINED3D_OK;
5672 }
5673
5674 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5675     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5676     if (PaletteNumber == NULL) {
5677         WARN("(%p) : returning Invalid Call\n", This);
5678         return WINED3DERR_INVALIDCALL;
5679     }
5680     /*TODO: stateblocks */
5681     *PaletteNumber = This->currentPalette;
5682     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5683     return WINED3D_OK;
5684 }
5685
5686 HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5687     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5688     static BOOL showFixmes = TRUE;
5689     if (showFixmes) {
5690         FIXME("(%p) : stub\n", This);
5691         showFixmes = FALSE;
5692     }
5693
5694     This->softwareVertexProcessing = bSoftware;
5695     return WINED3D_OK;
5696 }
5697
5698
5699 BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5700     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5701     static BOOL showFixmes = TRUE;
5702     if (showFixmes) {
5703         FIXME("(%p) : stub\n", This);
5704         showFixmes = FALSE;
5705     }
5706     return This->softwareVertexProcessing;
5707 }
5708
5709
5710 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5711     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5712     IWineD3DSwapChain *swapChain;
5713     HRESULT hr;
5714
5715     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5716
5717     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5718     if(hr == WINED3D_OK){
5719         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5720         IWineD3DSwapChain_Release(swapChain);
5721     }else{
5722         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5723     }
5724     return hr;
5725 }
5726
5727
5728 HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5729     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5730     static BOOL showfixmes = TRUE;
5731     if(nSegments != 0.0f) {
5732         if( showfixmes) {
5733             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5734             showfixmes = FALSE;
5735         }
5736     }
5737     return WINED3D_OK;
5738 }
5739
5740 float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5741     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5742     static BOOL showfixmes = TRUE;
5743     if( showfixmes) {
5744         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5745         showfixmes = FALSE;
5746     }
5747     return 0.0f;
5748 }
5749
5750 HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5751     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5752     /** TODO: remove casts to IWineD3DSurfaceImpl
5753      *       NOTE: move code to surface to accomplish this
5754       ****************************************/
5755     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5756     int srcWidth, srcHeight;
5757     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5758     WINED3DFORMAT destFormat, srcFormat;
5759     UINT          destSize;
5760     int destLeft, destTop;
5761     WINED3DPOOL       srcPool, destPool;
5762     int offset    = 0;
5763     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5764     glDescriptor *glDescription = NULL;
5765     GLenum textureDimensions = GL_TEXTURE_2D;
5766     IWineD3DBaseTexture *baseTexture;
5767
5768     WINED3DSURFACE_DESC  winedesc;
5769
5770     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5771     memset(&winedesc, 0, sizeof(winedesc));
5772     winedesc.Width  = &srcSurfaceWidth;
5773     winedesc.Height = &srcSurfaceHeight;
5774     winedesc.Pool   = &srcPool;
5775     winedesc.Format = &srcFormat;
5776
5777     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5778
5779     winedesc.Width  = &destSurfaceWidth;
5780     winedesc.Height = &destSurfaceHeight;
5781     winedesc.Pool   = &destPool;
5782     winedesc.Format = &destFormat;
5783     winedesc.Size   = &destSize;
5784
5785     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5786
5787     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5788         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5789         return WINED3DERR_INVALIDCALL;
5790     }
5791
5792     if (destFormat == WINED3DFMT_UNKNOWN) {
5793         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5794         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5795
5796         /* Get the update surface description */
5797         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5798     }
5799
5800     /* Make sure the surface is loaded and up to date */
5801     IWineD3DSurface_PreLoad(pDestinationSurface);
5802
5803     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5804
5805     ENTER_GL();
5806
5807     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5808     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5809     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
5810     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5811     destTop    = pDestPoint  ? pDestPoint->y : 0;
5812
5813
5814     /* This function doesn't support compressed textures
5815     the pitch is just bytesPerPixel * width */
5816     if(srcWidth != srcSurfaceWidth  || (pSourceRect != NULL && pSourceRect->left != 0) ){
5817         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5818         offset   += pSourceRect->left * pSrcSurface->bytesPerPixel;
5819         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5820     }
5821     /* TODO DXT formats */
5822
5823     if(pSourceRect != NULL && pSourceRect->top != 0){
5824        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5825     }
5826     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5827     ,This
5828     ,glDescription->level
5829     ,destLeft
5830     ,destTop
5831     ,srcWidth
5832     ,srcHeight
5833     ,glDescription->glFormat
5834     ,glDescription->glType
5835     ,IWineD3DSurface_GetData(pSourceSurface)
5836     );
5837
5838     /* Sanity check */
5839     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5840
5841         /* need to lock the surface to get the data */
5842         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5843     }
5844
5845     /* TODO: Cube and volume support */
5846     if(rowoffset != 0){
5847         /* not a whole row so we have to do it a line at a time */
5848         int j;
5849
5850         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5851         unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5852
5853         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5854
5855                 glTexSubImage2D(glDescription->target
5856                     ,glDescription->level
5857                     ,destLeft
5858                     ,j
5859                     ,srcWidth
5860                     ,1
5861                     ,glDescription->glFormat
5862                     ,glDescription->glType
5863                     ,data /* could be quicker using */
5864                 );
5865             data += rowoffset;
5866         }
5867
5868     } else { /* Full width, so just write out the whole texture */
5869
5870         if (WINED3DFMT_DXT1 == destFormat ||
5871             WINED3DFMT_DXT2 == destFormat ||
5872             WINED3DFMT_DXT3 == destFormat ||
5873             WINED3DFMT_DXT4 == destFormat ||
5874             WINED3DFMT_DXT5 == destFormat) {
5875             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5876                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5877                     /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5878                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5879                 } if (destFormat != srcFormat) {
5880                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5881                 } else {
5882                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5883                                                         glDescription->level,
5884                                                         glDescription->glFormatInternal,
5885                                                         srcWidth,
5886                                                         srcHeight,
5887                                                         0,
5888                                                         destSize,
5889                                                         IWineD3DSurface_GetData(pSourceSurface));
5890                 }
5891             } else {
5892                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5893             }
5894
5895
5896         } else {
5897             if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5898
5899                 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5900                 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5901                 data returned by GetData non-power2 width/height with hardware non-power2
5902                 pow2Width/height are set to surface width height, repacking isn't needed so it
5903                 doesn't matter which function gets called. */
5904                 glTexSubImage2D(glDescription->target
5905                         ,glDescription->level
5906                         ,destLeft
5907                         ,destTop
5908                         ,srcWidth
5909                         ,srcHeight
5910                         ,glDescription->glFormat
5911                         ,glDescription->glType
5912                         ,IWineD3DSurface_GetData(pSourceSurface)
5913                     );
5914             } else {
5915
5916                 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5917                 glTexSubImage2D(glDescription->target
5918                     ,glDescription->level
5919                     ,destLeft
5920                     ,destTop
5921                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5922                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5923                     ,glDescription->glFormat
5924                     ,glDescription->glType
5925                     ,IWineD3DSurface_GetData(pSourceSurface)
5926                 );
5927             }
5928
5929         }
5930      }
5931     checkGLcall("glTexSubImage2D");
5932
5933     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5934      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5935      * surface bigger than it needs to be hmm.. */
5936     if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5937         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5938         IWineD3DBaseTexture_Release(baseTexture);
5939     }
5940
5941     glDisable(textureDimensions); /* This needs to be managed better.... */
5942     LEAVE_GL();
5943
5944     return WINED3D_OK;
5945 }
5946
5947 /* Used by DirectX 8 */
5948 HRESULT  WINAPI  IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5949                                                 IWineD3DSurface* pSourceSurface,      CONST RECT* pSourceRectsArray, UINT cRects,
5950                                                 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5951
5952     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
5953     HRESULT              hr = WINED3D_OK;
5954     WINED3DFORMAT        srcFormat, destFormat;
5955     UINT                 srcWidth,  destWidth;
5956     UINT                 srcHeight, destHeight;
5957     UINT                 srcSize;
5958     WINED3DSURFACE_DESC  winedesc;
5959
5960     TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5961           pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5962
5963
5964     /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
5965     memset(&winedesc, 0, sizeof(winedesc));
5966
5967     winedesc.Format = &srcFormat;
5968     winedesc.Width  = &srcWidth;
5969     winedesc.Height = &srcHeight;
5970     winedesc.Size   = &srcSize;
5971     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5972
5973     winedesc.Format = &destFormat;
5974     winedesc.Width  = &destWidth;
5975     winedesc.Height = &destHeight;
5976     winedesc.Size   = NULL;
5977     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5978
5979     /* Check that the source and destination formats match */
5980     if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5981         WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5982         return WINED3DERR_INVALIDCALL;
5983     } else if (WINED3DFMT_UNKNOWN == destFormat) {
5984         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5985         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5986         destFormat = srcFormat;
5987     }
5988
5989     /* Quick if complete copy ... */
5990     if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5991
5992         if (srcWidth == destWidth && srcHeight == destHeight) {
5993             WINED3DLOCKED_RECT lrSrc;
5994             WINED3DLOCKED_RECT lrDst;
5995             IWineD3DSurface_LockRect(pSourceSurface,      &lrSrc, NULL, WINED3DLOCK_READONLY);
5996             IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5997             TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5998
5999             memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6000
6001             IWineD3DSurface_UnlockRect(pSourceSurface);
6002             IWineD3DSurface_UnlockRect(pDestinationSurface);
6003             TRACE("Unlocked src and dst\n");
6004
6005         } else {
6006
6007             FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6008             hr = WINED3DERR_INVALIDCALL;
6009          }
6010
6011     } else {
6012
6013         if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6014
6015             int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6016             unsigned int i;
6017
6018             /* Copy rect by rect */
6019             for (i = 0; i < cRects; ++i) {
6020                 CONST RECT*  r = &pSourceRectsArray[i];
6021                 CONST POINT* p = &pDestPointsArray[i];
6022                 int copyperline;
6023                 int j;
6024                 WINED3DLOCKED_RECT lrSrc;
6025                 WINED3DLOCKED_RECT lrDst;
6026                 RECT dest_rect;
6027
6028                 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6029                 if (srcFormat == WINED3DFMT_DXT1) {
6030                     copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6031                 } else {
6032                     copyperline = ((r->right - r->left) * bytesPerPixel);
6033                 }
6034
6035                 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6036                 dest_rect.left  = p->x;
6037                 dest_rect.top   = p->y;
6038                 dest_rect.right = p->x + (r->right - r->left);
6039                 dest_rect.bottom= p->y + (r->bottom - r->top);
6040                 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6041                 TRACE("Locked src and dst\n");
6042
6043                 /* Find where to start */
6044                 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6045                     memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6046                 }
6047                 IWineD3DSurface_UnlockRect(pSourceSurface);
6048                 IWineD3DSurface_UnlockRect(pDestinationSurface);
6049                 TRACE("Unlocked src and dst\n");
6050             }
6051         } else {
6052             FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6053             hr = WINED3DERR_INVALIDCALL;
6054         }
6055     }
6056
6057     return hr;
6058 }
6059
6060 /* Implementation details at http://developer.nvidia.com/attach/6494
6061 and
6062 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6063 hmm.. no longer supported use
6064 OpenGL evaluators or  tessellate surfaces within your application.
6065 */
6066
6067 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6068 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6069     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6070     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6071     FIXME("(%p) : Stub\n", This);
6072     return WINED3D_OK;
6073
6074 }
6075
6076 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6077 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6078     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6079     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6080     FIXME("(%p) : Stub\n", This);
6081     return WINED3D_OK;
6082 }
6083
6084 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6085     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6086     TRACE("(%p) Handle(%d)\n", This, Handle);
6087     FIXME("(%p) : Stub\n", This);
6088     return WINED3D_OK;
6089 }
6090
6091 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
6092     /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6093     fill a surface with a block of color!  */
6094     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6095     /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6096     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
6097     IWineD3DSwapChainImpl *container = NULL;
6098     BOOL isRenderTarget = FALSE;
6099     unsigned int width, height;
6100     unsigned int top, left;
6101     unsigned int u, v;
6102     DWORD       *data;
6103     TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
6104
6105     if (surface->resource.pool != WINED3DPOOL_DEFAULT) {
6106         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT surface\n");
6107         return WINED3DERR_INVALIDCALL;
6108     }
6109
6110     /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6111     if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
6112         if (WINED3DUSAGE_RENDERTARGET & surface->resource.usage) {
6113             /* TODO: make sure we set everything back to the way it was, and context management!
6114                 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6115                 vcheckGLcall("glIntegerv");
6116                 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6117                 vcheckGLcall("glIntegerv");
6118             */
6119             TRACE("Color fill to render targets may cause some graphics issues\n");
6120             if (pSurface == container->frontBuffer) {
6121                 glDrawBuffer(GL_FRONT);
6122             } else {
6123                 glDrawBuffer(GL_BACK);
6124             }
6125         } else {
6126             if (WINED3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
6127                 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
6128             } else {
6129                 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
6130             }
6131             if (container != NULL) {
6132                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6133             }
6134             /* we can use GL_STENCIL_INDEX etc...*/
6135             return WINED3D_OK;
6136         }
6137         if (container != NULL) {
6138             IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
6139         }
6140         isRenderTarget = TRUE;
6141     }
6142     /* TODO: drawing to GL_FRONT and GL_BACK */
6143     /* TODO: see if things can be speeded up by using the correct
6144      * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6145     if (pRect == NULL) {
6146         top    = 0;
6147         left   = 0;
6148         width  = surface->currentDesc.Width;
6149         height = surface->currentDesc.Height;
6150     } else {
6151         left   = pRect->x1;
6152         top    = pRect->y1;
6153         width  = pRect->x2 - left;
6154         height = pRect->y2 - top;
6155     }
6156
6157     data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
6158     /* Create a 'line' of color color, in the correct format for the surface */
6159     for (u = 0 ; u < width ; u ++) {
6160             data[u] = color;
6161     }
6162
6163     ENTER_GL();
6164     if (isRenderTarget == FALSE) {
6165         glDescriptor *glDesc;
6166         IWineD3DSurface_PreLoad(pSurface);
6167
6168         /* draw a block of the coloured line on the sufrace */
6169         IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
6170         for (v = 0 ; v< height;v++) {
6171             glTexSubImage2D(glDesc->target
6172                             ,glDesc->level /* level */
6173                             ,left
6174                             ,top + v
6175                             ,width
6176                             ,1 /* height */
6177                             ,GL_RGBA
6178                             ,GL_UNSIGNED_BYTE
6179                             ,data
6180                             );
6181         }
6182         checkGLcall("glTexSubImage2D");
6183         /* clean up */
6184         glDisable(glDesc->target);
6185     } else {
6186         /** FIXME: Using GLClear may be faster **/
6187         glRasterPos2i(left, top);
6188         glPixelZoom((float)width ,(float)height);
6189         glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
6190         checkGLcall("glDrawPixels");
6191     }
6192     HeapFree(GetProcessHeap(), 0, data);
6193     LEAVE_GL();
6194     return WINED3D_OK;
6195
6196 }
6197
6198 /* rendertarget and deptth stencil functions */
6199 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6200     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6201
6202     /* FIXME: Implelent RenderTargetIndex >0 */
6203     if(RenderTargetIndex > 0)
6204         FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
6205
6206     *ppRenderTarget = This->renderTarget;
6207     TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6208     /* Note inc ref on returned surface */
6209     if(*ppRenderTarget != NULL)
6210         IWineD3DSurface_AddRef(*ppRenderTarget);
6211     return WINED3D_OK;
6212 }
6213
6214 HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6215     FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
6216     return WINED3DERR_INVALIDCALL;
6217 }
6218
6219 HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6220     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6221     *ppZStencilSurface = This->depthStencilBuffer;
6222     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
6223
6224     if(*ppZStencilSurface != NULL) {
6225         /* Note inc ref on returned surface */
6226         IWineD3DSurface_AddRef(*ppZStencilSurface);
6227     }
6228     return WINED3D_OK;
6229 }
6230
6231 /* internal static helper functions */
6232 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6233                                                 IWineD3DSurface *RenderSurface);
6234
6235 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6236     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6237     HRESULT  hr = WINED3D_OK;
6238     WINED3DVIEWPORT viewport;
6239
6240     TRACE("(%p) Swapping rendertarget\n",This);
6241     if (RenderTargetIndex > 0) {
6242         FIXME("(%p) Render targets other than the first are not supported\n",This);
6243         RenderTargetIndex = 0;
6244     }
6245
6246     /* MSDN says that null disables the render target
6247     but a device must always be associated with a render target
6248     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6249
6250     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6251     for more details
6252     */
6253     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6254         FIXME("Trying to set render target 0 to NULL\n");
6255         return WINED3DERR_INVALIDCALL;
6256     }
6257     /* TODO: replace Impl* usage with interface usage */
6258     if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6259         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);
6260         return WINED3DERR_INVALIDCALL;
6261     }
6262     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6263      *        builds, but I think wine counts as a 'debug' build for now.
6264       ******************************/
6265     /* If we are trying to set what we already have, don't bother */
6266     if (pRenderTarget == This->renderTarget) {
6267         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6268     } else {
6269         /* Otherwise, set the render target up */
6270
6271         if (FALSE == This->sceneEnded) {
6272             IWineD3DDevice_EndScene(iface);
6273         }
6274         TRACE("clearing renderer\n");
6275         /* IWineD3DDeviceImpl_CleanRender(iface); */
6276         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6277         depending on the renter target implementation being used.
6278         A shared context implementation will share all buffers between all rendertargets (including swapchains),
6279         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6280         stencil buffer and incure an extra memory overhead */
6281         hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6282     }
6283
6284     if (SUCCEEDED(hr)) {
6285         /* Finally, reset the viewport as the MSDN states. */
6286         /* TODO: Replace impl usage */
6287         viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6288         viewport.Width  = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6289         viewport.X      = 0;
6290         viewport.Y      = 0;
6291         viewport.MaxZ   = 1.0f;
6292         viewport.MinZ   = 0.0f;
6293         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6294     } else {
6295         FIXME("Unknown error setting the render target\n");
6296     }
6297     This->sceneEnded = FALSE;
6298     return hr;
6299 }
6300
6301 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6302     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6303     HRESULT  hr = WINED3D_OK;
6304     IWineD3DSurface *tmp;
6305
6306     TRACE("(%p) Swapping z-buffer\n",This);
6307
6308     if (pNewZStencil == This->stencilBufferTarget) {
6309         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6310     } else {
6311         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6312         * depending on the renter target implementation being used.
6313         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6314         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6315         * stencil buffer and incure an extra memory overhead
6316          ******************************************************/
6317
6318
6319         tmp = This->stencilBufferTarget;
6320         This->stencilBufferTarget = pNewZStencil;
6321         /* should we be calling the parent or the wined3d surface? */
6322         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6323         if (NULL != tmp) IWineD3DSurface_Release(tmp);
6324         hr = WINED3D_OK;
6325         /** TODO: glEnable/glDisable on depth/stencil    depending on
6326          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
6327           **********************************************************/
6328     }
6329
6330     return hr;
6331 }
6332
6333
6334 #ifdef GL_VERSION_1_3
6335 /* Internal functions not in DirectX */
6336  /** TODO: move this off to the opengl context manager
6337  *(the swapchain doesn't need to know anything about offscreen rendering!)
6338   ****************************************************/
6339
6340 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6341 {
6342     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6343
6344     TRACE("(%p), %p\n", This, swapchain);
6345
6346     if (swapchain->win != swapchain->drawable) {
6347         /* Set everything back the way it ws */
6348         swapchain->render_ctx = swapchain->glCtx;
6349         swapchain->drawable   = swapchain->win;
6350     }
6351     return WINED3D_OK;
6352 }
6353
6354 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6355 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6356     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6357     int i;
6358     unsigned int width;
6359     unsigned int height;
6360     WINED3DFORMAT format;
6361     WINED3DSURFACE_DESC surfaceDesc;
6362     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6363     surfaceDesc.Width  = &width;
6364     surfaceDesc.Height = &height;
6365     surfaceDesc.Format = &format;
6366     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6367     *context = NULL;
6368     /* I need a get width/height function (and should do something with the format) */
6369     for (i = 0; i < CONTEXT_CACHE; ++i) {
6370         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6371         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6372         the pSurface can be set to 0 allowing it to be reused from cache **/
6373         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6374           && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6375             *context = &This->contextCache[i];
6376             break;
6377         }
6378         if (This->contextCache[i].Width == 0) {
6379             This->contextCache[i].pSurface = pSurface;
6380             This->contextCache[i].Width    = width;
6381             This->contextCache[i].Height   = height;
6382             *context = &This->contextCache[i];
6383             break;
6384         }
6385     }
6386     if (i == CONTEXT_CACHE) {
6387         int minUsage = 0x7FFFFFFF; /* MAX_INT */
6388         glContext *dropContext = 0;
6389         for (i = 0; i < CONTEXT_CACHE; i++) {
6390             if (This->contextCache[i].usedcount < minUsage) {
6391                 dropContext = &This->contextCache[i];
6392                 minUsage = This->contextCache[i].usedcount;
6393             }
6394         }
6395         /* clean up the context (this doesn't work for ATI at the moment */
6396 #if 0
6397         glXDestroyContext(swapchain->display, dropContext->context);
6398         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6399 #endif
6400         FIXME("Leak\n");
6401         dropContext->Width = 0;
6402         dropContext->pSurface = pSurface;
6403         *context = dropContext;
6404     } else {
6405         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6406           for (i = 0; i < CONTEXT_CACHE; i++) {
6407              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6408           }
6409         }
6410     }
6411     if (*context != NULL)
6412         return WINED3D_OK;
6413     else
6414         return E_OUTOFMEMORY;
6415 }
6416 #endif
6417
6418 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6419 * the functionality needs splitting up so that we don't do more than we should do.
6420 * this only seems to impact performance a little.
6421  ******************************/
6422 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6423                                                IWineD3DSurface *RenderSurface) {
6424     HRESULT ret =  WINED3DERR_INVALIDCALL;
6425
6426     /**
6427     * Currently only active for GLX >= 1.3
6428     * for others versions we'll have to use GLXPixmaps
6429     *
6430     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6431     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6432     * so only check OpenGL version
6433     * ..........................
6434     * I don't believe that it is a problem with NVidia headers,
6435     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6436     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6437     * ATI Note:
6438     * Your application will report GLX version 1.2 on glXQueryVersion.
6439     * However, it is safe to call the GLX 1.3 functions as described below.
6440     */
6441 #if defined(GL_VERSION_1_3)
6442
6443     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6444     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6445     IWineD3DSurface *tmp;
6446     /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6447     GLXFBConfig* cfgs = NULL;
6448     int nCfgs = 0;
6449     int attribs[256];
6450     int nAttribs = 0;
6451     IWineD3DSwapChain     *currentSwapchain;
6452     IWineD3DSwapChainImpl *swapchain;
6453     /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6454     * but switch them off if the StencilSurface is set to NULL
6455     ** *********************************************************/
6456     D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6457     D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6458
6459     /**TODO:
6460         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6461         it StencilSurface != NULL && zBufferTarget == NULL switch it on
6462     */
6463
6464 #define PUSH1(att)        attribs[nAttribs++] = (att);
6465 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6466
6467     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6468
6469     /** TODO: remove the reff to Impl (context manager should fix this!) **/
6470     IWineD3DSwapChainImpl *impSwapChain;
6471     IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
6472     if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
6473         ERR("(%p) Failed to get a the implicit swapchain\n", iface);
6474     }
6475
6476     ENTER_GL();
6477
6478     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6479     PUSH2(GLX_X_RENDERABLE,  TRUE);
6480     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
6481     TRACE("calling makeglcfg\n");
6482     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6483     PUSH1(None);
6484
6485     TRACE("calling chooseFGConfig\n");
6486     cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6487                                                      attribs, &nCfgs);
6488
6489     if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
6490         /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6491            why we failed and only show this message once! */
6492         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"); /**/
6493         nAttribs = 0;
6494         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6495        /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
6496         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
6497         PUSH2(GLX_DOUBLEBUFFER, FALSE);
6498         TRACE("calling makeglcfg\n");
6499         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6500         PUSH1(None);
6501         cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6502                                                         attribs, &nCfgs);
6503     }
6504
6505     if (NULL != cfgs) {
6506 #ifdef EXTRA_TRACES
6507         int i;
6508         for (i = 0; i < nCfgs; ++i) {
6509             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6510             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6511             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6512         }
6513
6514         if (NULL != This->renderTarget) {
6515             glFlush();
6516             vcheckGLcall("glFlush");
6517             /** This is only useful if the old render target was a swapchain,
6518             * we need to supercede this with a function that displays
6519             * the current buffer on the screen. This is easy to do in glx1.3 but
6520             * we need to do copy-write pixels in glx 1.2.
6521             ************************************************/
6522             glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6523
6524             printf("Hit Enter to get next frame ...\n");
6525             getchar();
6526         }
6527 #endif
6528     }
6529
6530     if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != WINED3D_OK) {
6531         /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6532         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
6533     }
6534
6535     /**
6536     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6537     *  renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6538      **********************************************************************/
6539     if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
6540         /* We also need to make sure that the lights &co are also in the context of the swapchains */
6541         /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6542         TRACE("making swapchain active\n");
6543         if (RenderSurface != This->renderTarget) {
6544             if (RenderSurface ==  swapchain->backBuffer) {
6545             } else {
6546                 /* This could be flagged so that some operations work directly with the front buffer */
6547                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
6548             }
6549             if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6550             == False) {
6551                 TRACE("Error in setting current context: context %p drawable %ld !\n",
6552                        impSwapChain->glCtx, impSwapChain->win);
6553             }
6554
6555             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6556         }
6557         checkGLcall("glXMakeContextCurrent");
6558
6559         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6560     }
6561     else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6562
6563         /** ********************************************************************
6564         * This is a quickly hacked out implementation of offscreen textures.
6565         * It will work in most cases but there may be problems if the client
6566         * modifies the texture directly, or expects the contents of the rendertarget
6567         * to be persistent.
6568         *
6569         * There are some real speed vs compatibility issues here:
6570         *    we should really use a new context for every texture, but that eats ram.
6571         *    we should also be restoring the texture to the pbuffer but that eats CPU
6572         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6573         *    but if this means reusing the display backbuffer then we need to make sure that
6574         *    states are correctly preserved.
6575         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6576         * and gain a good performance increase at the cost of compatibility.
6577         * I would suggest that, when this is the case, a user configurable flag be made
6578         * available, allowing the user to choose the best emulated experience for them.
6579          *********************************************************************/
6580
6581         XVisualInfo *visinfo;
6582         glContext   *newContext;
6583
6584         /* Here were using a shared context model */
6585         if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6586             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6587         }
6588
6589         /* If the context doesn't exist then create a new one */
6590         /* TODO: This should really be part of findGlContext */
6591         if (NULL == newContext->context) {
6592
6593             TRACE("making new buffer\n");
6594             nAttribs = 0;
6595             PUSH2(GLX_PBUFFER_WIDTH,  newContext->Width);
6596             PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6597             PUSH1(None);
6598
6599             newContext->drawable  = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6600
6601             /** ****************************************
6602             *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6603             *they note:
6604             *   In future releases, we may provide the calls glXCreateNewContext,
6605             *   glXQueryDrawable and glXMakeContextCurrent.
6606             *    so until then we have to use glXGetVisualFromFBConfig &co..
6607             ********************************************/
6608
6609
6610             visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6611             if (!visinfo) {
6612                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6613             } else {
6614                 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx,  GL_TRUE);
6615                 XFree(visinfo);
6616             }
6617         }
6618         if (NULL == newContext || NULL == newContext->context) {
6619             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6620         } else {
6621             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6622             if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6623                 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6624             }
6625
6626             /* Clean up the old context */
6627             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6628             /* Set the current context of the swapchain to the new context */
6629             impSwapChain->drawable   = newContext->drawable;
6630             impSwapChain->render_ctx = newContext->context;
6631         }
6632     }
6633
6634 #if 1 /* Apply the stateblock to the new context
6635 FIXME: This is a bit of a hack, each context should know it's own state,
6636 the directX current directX state should then be applied to the context */
6637     {
6638         BOOL oldRecording;
6639         IWineD3DStateBlockImpl *oldUpdateStateBlock;
6640         oldUpdateStateBlock = This->updateStateBlock;
6641         oldRecording= This->isRecordingState;
6642         This->isRecordingState = FALSE;
6643         This->updateStateBlock = This->stateBlock;
6644         IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6645
6646         This->isRecordingState = oldRecording;
6647         This->updateStateBlock = oldUpdateStateBlock;
6648     }
6649 #endif
6650
6651
6652     /* clean up the current rendertargets swapchain (if it belonged to one) */
6653     if (currentSwapchain != NULL) {
6654         IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6655     }
6656
6657     /* Were done with the opengl context management, setup the rendertargets */
6658
6659     tmp = This->renderTarget;
6660     This->renderTarget = RenderSurface;
6661     IWineD3DSurface_AddRef(This->renderTarget);
6662     IWineD3DSurface_Release(tmp);
6663
6664
6665
6666     {
6667         DWORD value;
6668         /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6669         /* Check that the container is not a swapchain member */
6670
6671         IWineD3DSwapChain *tmpSwapChain;
6672         if (WINED3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6673             This->renderUpsideDown = TRUE;
6674         }else{
6675             This->renderUpsideDown = FALSE;
6676             IWineD3DSwapChain_Release(tmpSwapChain);
6677         }
6678         /* Force updating the cull mode */
6679         TRACE("setting render state\n");
6680         IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6681         IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6682
6683         /* Force updating projection matrix */
6684         This->last_was_rhw = FALSE;
6685         This->proj_valid = FALSE;
6686     }
6687
6688     ret = WINED3D_OK;
6689
6690     if (cfgs != NULL) {
6691         XFree(cfgs);
6692     } else {
6693         ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6694             debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6695     }
6696
6697 #undef PUSH1
6698 #undef PUSH2
6699     if ( NULL != impSwapChain) {
6700         IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6701     }
6702     LEAVE_GL();
6703
6704 #endif
6705     return ret;
6706 }
6707
6708 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6709                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6710     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6711     /* TODO: the use of Impl is deprecated. */
6712     /* some basic validation checks */
6713     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6714
6715     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6716
6717     if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6718       ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6719       return WINED3DERR_INVALIDCALL;
6720     }
6721     if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6722       ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6723       return WINED3DERR_INVALIDCALL;
6724     }
6725     /* TODO: make the cursor 'real' */
6726
6727     This->xHotSpot = XHotSpot;
6728     This->yHotSpot = YHotSpot;
6729
6730     return WINED3D_OK;
6731 }
6732
6733 void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6734     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6735     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6736
6737     This->xScreenSpace = XScreenSpace;
6738     This->yScreenSpace = YScreenSpace;
6739
6740     return;
6741
6742 }
6743
6744 BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6745     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6746     TRACE("(%p) : visible(%d)\n", This, bShow);
6747
6748     This->bCursorVisible = bShow;
6749
6750     return WINED3D_OK;
6751 }
6752
6753 HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6754     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6755     TRACE("(%p) : state (%lu)\n", This, This->state);
6756     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6757     switch (This->state) {
6758     case WINED3D_OK:
6759         return WINED3D_OK;
6760     case WINED3DERR_DEVICELOST:
6761         {
6762             ResourceList *resourceList  = This->resources;
6763             while (NULL != resourceList) {
6764                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6765                 return WINED3DERR_DEVICENOTRESET;
6766                 resourceList = resourceList->next;
6767             }
6768             return WINED3DERR_DEVICELOST;
6769         }
6770     case WINED3DERR_DRIVERINTERNALERROR:
6771         return WINED3DERR_DRIVERINTERNALERROR;
6772     }
6773
6774     /* Unknown state */
6775     return WINED3DERR_DRIVERINTERNALERROR;
6776 }
6777
6778
6779 HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6780     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6781     /** FIXME: Resource tracking needs to be done,
6782     * The closes we can do to this is set the priorities of all managed textures low
6783     * and then reset them.
6784      ***********************************************************/
6785     FIXME("(%p) : stub\n", This);
6786     return WINED3D_OK;
6787 }
6788
6789 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6790     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6791     /** FIXME: Resource trascking needs to be done.
6792     * in effect this pulls all non only default
6793     * textures out of video memory and deletes all glTextures (glDeleteTextures)
6794     * and should clear down the context and set it up according to pPresentationParameters
6795      ***********************************************************/
6796     FIXME("(%p) : stub\n", This);
6797     return WINED3D_OK;
6798 }
6799
6800 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6801     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6802     /** FIXME: always true at the moment **/
6803     if(bEnableDialogs == FALSE) {
6804         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6805     }
6806     return WINED3D_OK;
6807 }
6808
6809
6810 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6811     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6812     TRACE("(%p) : pParameters %p\n", This, pParameters);
6813
6814     *pParameters = This->createParms;
6815     return WINED3D_OK;
6816 }
6817
6818 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6819     IWineD3DSwapChain *swapchain;
6820     HRESULT hrc = WINED3D_OK;
6821
6822     TRACE("Relaying  to swapchain\n");
6823
6824     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6825         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6826         IWineD3DSwapChain_Release(swapchain);
6827     }
6828     return;
6829 }
6830
6831 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6832     IWineD3DSwapChain *swapchain;
6833     HRESULT hrc = WINED3D_OK;
6834
6835     TRACE("Relaying  to swapchain\n");
6836
6837     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6838         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6839         IWineD3DSwapChain_Release(swapchain);
6840     }
6841     return;
6842 }
6843
6844
6845 /** ********************************************************
6846 *   Notification functions
6847 ** ********************************************************/
6848 /** This function must be called in the release of a resource when ref == 0,
6849 * the contents of resource must still be correct,
6850 * any handels to other resource held by the caller must be closed
6851 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6852  *****************************************************/
6853 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6854     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6855     ResourceList* resourceList;
6856
6857     TRACE("(%p) : resource %p\n", This, resource);
6858 #if 0
6859     EnterCriticalSection(&resourceStoreCriticalSection);
6860 #endif
6861     /* add a new texture to the frot of the linked list */
6862     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6863     resourceList->resource = resource;
6864
6865     /* Get the old head */
6866     resourceList->next = This->resources;
6867
6868     This->resources = resourceList;
6869     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6870
6871 #if 0
6872     LeaveCriticalSection(&resourceStoreCriticalSection);
6873 #endif
6874     return;
6875 }
6876
6877 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6878     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6879     ResourceList* resourceList = NULL;
6880     ResourceList* previousResourceList = NULL;
6881     
6882     TRACE("(%p) : resource %p\n", This, resource);
6883
6884 #if 0
6885     EnterCriticalSection(&resourceStoreCriticalSection);
6886 #endif
6887     resourceList = This->resources;
6888
6889     while (resourceList != NULL) {
6890         if(resourceList->resource == resource) break;
6891         previousResourceList = resourceList;
6892         resourceList = resourceList->next;
6893     }
6894
6895     if (resourceList == NULL) {
6896         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6897 #if 0
6898         LeaveCriticalSection(&resourceStoreCriticalSection);
6899 #endif
6900         return;
6901     } else {
6902             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6903     }
6904     /* make sure we don't leave a hole in the list */
6905     if (previousResourceList != NULL) {
6906         previousResourceList->next = resourceList->next;
6907     } else {
6908         This->resources = resourceList->next;
6909     }
6910
6911 #if 0
6912     LeaveCriticalSection(&resourceStoreCriticalSection);
6913 #endif
6914     return;
6915 }
6916
6917
6918 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6919     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6920     int counter;
6921
6922     TRACE("(%p) : resource %p\n", This, resource);
6923     switch(IWineD3DResource_GetType(resource)){
6924         case WINED3DRTYPE_SURFACE:
6925         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6926         break;
6927         case WINED3DRTYPE_TEXTURE:
6928         case WINED3DRTYPE_CUBETEXTURE:
6929         case WINED3DRTYPE_VOLUMETEXTURE:
6930                 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6931                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6932                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6933                         This->stateBlock->textures[counter] = NULL;
6934                     }
6935                     if (This->updateStateBlock != This->stateBlock ){
6936                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6937                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6938                             This->updateStateBlock->textures[counter] = NULL;
6939                         }
6940                     }
6941                 }
6942         break;
6943         case WINED3DRTYPE_VOLUME:
6944         /* TODO: nothing really? */
6945         break;
6946         case WINED3DRTYPE_VERTEXBUFFER:
6947         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6948         {
6949             int streamNumber;
6950             TRACE("Cleaning up stream pointers\n");
6951
6952             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6953                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6954                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6955                 */
6956                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6957                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6958                         FIXME("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
6959                         This->updateStateBlock->streamSource[streamNumber] = 0;
6960                         /* Set changed flag? */
6961                     }
6962                 }
6963                 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) */
6964                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6965                         TRACE("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
6966                         This->stateBlock->streamSource[streamNumber] = 0;
6967                     }
6968                 }
6969 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6970                  else { /* This shouldn't happen */
6971                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6972                 }
6973 #endif
6974
6975             }
6976         }
6977         break;
6978         case WINED3DRTYPE_INDEXBUFFER:
6979         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6980         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6981             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6982                 This->updateStateBlock->pIndexData =  NULL;
6983             }
6984         }
6985         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6986             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6987                 This->stateBlock->pIndexData =  NULL;
6988             }
6989         }
6990
6991         break;
6992         default:
6993         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6994         break;
6995     }
6996
6997
6998     /* Remove the resoruce from the resourceStore */
6999     IWineD3DDeviceImpl_RemoveResource(iface, resource);
7000
7001     TRACE("Resource released\n");
7002
7003 }
7004
7005
7006 /** This function is to be called by the swapchain when it is released and it's ref = 0
7007  *****************************************************/
7008 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
7009     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7010     SwapChainList **nextSwapchain;
7011     nextSwapchain = &This->swapchains;
7012
7013     /* Check to see if the swapchian is being used as the render target */
7014     if (This->renderTarget != NULL) {
7015         IWineD3DSurface *swapchainBackBuffer;
7016
7017         IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
7018         if (This->renderTarget == swapchainBackBuffer) {
7019             /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
7020             FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
7021         }
7022     }
7023
7024     /* Go through the swapchain list and try to find the swapchain being released */
7025     while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
7026         nextSwapchain = &(*nextSwapchain)->next;
7027     }
7028
7029     /* Check to see if we found the swapchain */
7030     if (NULL != *nextSwapchain) {
7031         /* We found the swapchain so remove it from the list */
7032         TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
7033         HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
7034         *nextSwapchain = (*nextSwapchain)->next;
7035     } else {
7036         /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
7037         FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
7038     }
7039
7040     TRACE("swapchain (%p) released\n", swapChain);
7041     return;
7042 }
7043
7044 /**********************************************************
7045  * IWineD3DDevice VTbl follows
7046  **********************************************************/
7047
7048 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7049 {
7050     /*** IUnknown methods ***/
7051     IWineD3DDeviceImpl_QueryInterface,
7052     IWineD3DDeviceImpl_AddRef,
7053     IWineD3DDeviceImpl_Release,
7054     /*** IWineD3DDevice methods ***/
7055     IWineD3DDeviceImpl_GetParent,
7056     /*** Creation methods**/
7057     IWineD3DDeviceImpl_CreateVertexBuffer,
7058     IWineD3DDeviceImpl_CreateIndexBuffer,
7059     IWineD3DDeviceImpl_CreateStateBlock,
7060     IWineD3DDeviceImpl_CreateSurface,
7061     IWineD3DDeviceImpl_CreateTexture,
7062     IWineD3DDeviceImpl_CreateVolumeTexture,
7063     IWineD3DDeviceImpl_CreateVolume,
7064     IWineD3DDeviceImpl_CreateCubeTexture,
7065     IWineD3DDeviceImpl_CreateQuery,
7066     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7067     IWineD3DDeviceImpl_CreateVertexDeclaration,
7068     IWineD3DDeviceImpl_CreateVertexShader,
7069     IWineD3DDeviceImpl_CreatePixelShader,
7070     IWineD3DDeviceImpl_CreatePalette,
7071     /*** Odd functions **/
7072     IWineD3DDeviceImpl_Init3D,
7073     IWineD3DDeviceImpl_Uninit3D,
7074     IWineD3DDeviceImpl_EnumDisplayModes,
7075     IWineD3DDeviceImpl_EvictManagedResources,
7076     IWineD3DDeviceImpl_GetAvailableTextureMem,
7077     IWineD3DDeviceImpl_GetBackBuffer,
7078     IWineD3DDeviceImpl_GetCreationParameters,
7079     IWineD3DDeviceImpl_GetDeviceCaps,
7080     IWineD3DDeviceImpl_GetDirect3D,
7081     IWineD3DDeviceImpl_GetDisplayMode,
7082     IWineD3DDeviceImpl_SetDisplayMode,
7083     IWineD3DDeviceImpl_GetHWND,
7084     IWineD3DDeviceImpl_SetHWND,
7085     IWineD3DDeviceImpl_GetNumberOfSwapChains,
7086     IWineD3DDeviceImpl_GetRasterStatus,
7087     IWineD3DDeviceImpl_GetSwapChain,
7088     IWineD3DDeviceImpl_Reset,
7089     IWineD3DDeviceImpl_SetDialogBoxMode,
7090     IWineD3DDeviceImpl_SetCursorProperties,
7091     IWineD3DDeviceImpl_SetCursorPosition,
7092     IWineD3DDeviceImpl_ShowCursor,
7093     IWineD3DDeviceImpl_TestCooperativeLevel,
7094     IWineD3DDeviceImpl_EnumZBufferFormats,
7095     IWineD3DDeviceImpl_EnumTextureFormats,
7096     /*** Getters and setters **/
7097     IWineD3DDeviceImpl_SetClipPlane,
7098     IWineD3DDeviceImpl_GetClipPlane,
7099     IWineD3DDeviceImpl_SetClipStatus,
7100     IWineD3DDeviceImpl_GetClipStatus,
7101     IWineD3DDeviceImpl_SetCurrentTexturePalette,
7102     IWineD3DDeviceImpl_GetCurrentTexturePalette,
7103     IWineD3DDeviceImpl_SetDepthStencilSurface,
7104     IWineD3DDeviceImpl_GetDepthStencilSurface,
7105     IWineD3DDeviceImpl_SetFVF,
7106     IWineD3DDeviceImpl_GetFVF,
7107     IWineD3DDeviceImpl_SetGammaRamp,
7108     IWineD3DDeviceImpl_GetGammaRamp,
7109     IWineD3DDeviceImpl_SetIndices,
7110     IWineD3DDeviceImpl_GetIndices,
7111     IWineD3DDeviceImpl_SetLight,
7112     IWineD3DDeviceImpl_GetLight,
7113     IWineD3DDeviceImpl_SetLightEnable,
7114     IWineD3DDeviceImpl_GetLightEnable,
7115     IWineD3DDeviceImpl_SetMaterial,
7116     IWineD3DDeviceImpl_GetMaterial,
7117     IWineD3DDeviceImpl_SetNPatchMode,
7118     IWineD3DDeviceImpl_GetNPatchMode,
7119     IWineD3DDeviceImpl_SetPaletteEntries,
7120     IWineD3DDeviceImpl_GetPaletteEntries,
7121     IWineD3DDeviceImpl_SetPixelShader,
7122     IWineD3DDeviceImpl_GetPixelShader,
7123     IWineD3DDeviceImpl_SetPixelShaderConstant,
7124     IWineD3DDeviceImpl_GetPixelShaderConstant,
7125     IWineD3DDeviceImpl_SetPixelShaderConstantB,
7126     IWineD3DDeviceImpl_GetPixelShaderConstantB,
7127     IWineD3DDeviceImpl_SetPixelShaderConstantI,
7128     IWineD3DDeviceImpl_GetPixelShaderConstantI,
7129     IWineD3DDeviceImpl_SetPixelShaderConstantF,
7130     IWineD3DDeviceImpl_GetPixelShaderConstantF,
7131     IWineD3DDeviceImpl_SetPixelShaderConstantN,
7132     IWineD3DDeviceImpl_SetRenderState,
7133     IWineD3DDeviceImpl_GetRenderState,
7134     IWineD3DDeviceImpl_SetRenderTarget,
7135     IWineD3DDeviceImpl_GetRenderTarget,
7136     IWineD3DDeviceImpl_SetFrontBackBuffers,
7137     IWineD3DDeviceImpl_SetSamplerState,
7138     IWineD3DDeviceImpl_GetSamplerState,
7139     IWineD3DDeviceImpl_SetScissorRect,
7140     IWineD3DDeviceImpl_GetScissorRect,
7141     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7142     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7143     IWineD3DDeviceImpl_SetStreamSource,
7144     IWineD3DDeviceImpl_GetStreamSource,
7145     IWineD3DDeviceImpl_SetStreamSourceFreq,
7146     IWineD3DDeviceImpl_GetStreamSourceFreq,
7147     IWineD3DDeviceImpl_SetTexture,
7148     IWineD3DDeviceImpl_GetTexture,
7149     IWineD3DDeviceImpl_SetTextureStageState,
7150     IWineD3DDeviceImpl_GetTextureStageState,
7151     IWineD3DDeviceImpl_SetTransform,
7152     IWineD3DDeviceImpl_GetTransform,
7153     IWineD3DDeviceImpl_SetVertexDeclaration,
7154     IWineD3DDeviceImpl_GetVertexDeclaration,
7155     IWineD3DDeviceImpl_SetVertexShader,
7156     IWineD3DDeviceImpl_GetVertexShader,
7157     IWineD3DDeviceImpl_SetVertexShaderConstant,
7158     IWineD3DDeviceImpl_GetVertexShaderConstant,
7159     IWineD3DDeviceImpl_SetVertexShaderConstantB,
7160     IWineD3DDeviceImpl_GetVertexShaderConstantB,
7161     IWineD3DDeviceImpl_SetVertexShaderConstantI,
7162     IWineD3DDeviceImpl_GetVertexShaderConstantI,
7163     IWineD3DDeviceImpl_SetVertexShaderConstantF,
7164     IWineD3DDeviceImpl_GetVertexShaderConstantF,
7165     IWineD3DDeviceImpl_SetVertexShaderConstantN,
7166     IWineD3DDeviceImpl_SetViewport,
7167     IWineD3DDeviceImpl_GetViewport,
7168     IWineD3DDeviceImpl_MultiplyTransform,
7169     IWineD3DDeviceImpl_ValidateDevice,
7170     IWineD3DDeviceImpl_ProcessVertices,
7171     /*** State block ***/
7172     IWineD3DDeviceImpl_BeginStateBlock,
7173     IWineD3DDeviceImpl_EndStateBlock,
7174     /*** Scene management ***/
7175     IWineD3DDeviceImpl_BeginScene,
7176     IWineD3DDeviceImpl_EndScene,
7177     IWineD3DDeviceImpl_Present,
7178     IWineD3DDeviceImpl_Clear,
7179     /*** Drawing ***/
7180     IWineD3DDeviceImpl_DrawPrimitive,
7181     IWineD3DDeviceImpl_DrawIndexedPrimitive,
7182     IWineD3DDeviceImpl_DrawPrimitiveUP,
7183     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7184     IWineD3DDeviceImpl_DrawPrimitiveStrided,
7185     IWineD3DDeviceImpl_DrawRectPatch,
7186     IWineD3DDeviceImpl_DrawTriPatch,
7187     IWineD3DDeviceImpl_DeletePatch,
7188     IWineD3DDeviceImpl_ColorFill,
7189     IWineD3DDeviceImpl_UpdateTexture,
7190     IWineD3DDeviceImpl_UpdateSurface,
7191     IWineD3DDeviceImpl_CopyRects,
7192     IWineD3DDeviceImpl_StretchRect,
7193     IWineD3DDeviceImpl_GetRenderTargetData,
7194     IWineD3DDeviceImpl_GetFrontBufferData,
7195     /*** Internal use IWineD3DDevice methods ***/
7196     IWineD3DDeviceImpl_SetupTextureStates,
7197     /*** object tracking ***/
7198     IWineD3DDeviceImpl_SwapChainReleased,
7199     IWineD3DDeviceImpl_ResourceReleased
7200 };
7201
7202
7203 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7204     WINED3DRS_ALPHABLENDENABLE   ,
7205     WINED3DRS_ALPHAFUNC          ,
7206     WINED3DRS_ALPHAREF           ,
7207     WINED3DRS_ALPHATESTENABLE    ,
7208     WINED3DRS_BLENDOP            ,
7209     WINED3DRS_COLORWRITEENABLE   ,
7210     WINED3DRS_DESTBLEND          ,
7211     WINED3DRS_DITHERENABLE       ,
7212     WINED3DRS_FILLMODE           ,
7213     WINED3DRS_FOGDENSITY         ,
7214     WINED3DRS_FOGEND             ,
7215     WINED3DRS_FOGSTART           ,
7216     WINED3DRS_LASTPIXEL          ,
7217     WINED3DRS_SHADEMODE          ,
7218     WINED3DRS_SRCBLEND           ,
7219     WINED3DRS_STENCILENABLE      ,
7220     WINED3DRS_STENCILFAIL        ,
7221     WINED3DRS_STENCILFUNC        ,
7222     WINED3DRS_STENCILMASK        ,
7223     WINED3DRS_STENCILPASS        ,
7224     WINED3DRS_STENCILREF         ,
7225     WINED3DRS_STENCILWRITEMASK   ,
7226     WINED3DRS_STENCILZFAIL       ,
7227     WINED3DRS_TEXTUREFACTOR      ,
7228     WINED3DRS_WRAP0              ,
7229     WINED3DRS_WRAP1              ,
7230     WINED3DRS_WRAP2              ,
7231     WINED3DRS_WRAP3              ,
7232     WINED3DRS_WRAP4              ,
7233     WINED3DRS_WRAP5              ,
7234     WINED3DRS_WRAP6              ,
7235     WINED3DRS_WRAP7              ,
7236     WINED3DRS_ZENABLE            ,
7237     WINED3DRS_ZFUNC              ,
7238     WINED3DRS_ZWRITEENABLE
7239 };
7240
7241 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7242     WINED3DTSS_ADDRESSW              ,
7243     WINED3DTSS_ALPHAARG0             ,
7244     WINED3DTSS_ALPHAARG1             ,
7245     WINED3DTSS_ALPHAARG2             ,
7246     WINED3DTSS_ALPHAOP               ,
7247     WINED3DTSS_BUMPENVLOFFSET        ,
7248     WINED3DTSS_BUMPENVLSCALE         ,
7249     WINED3DTSS_BUMPENVMAT00          ,
7250     WINED3DTSS_BUMPENVMAT01          ,
7251     WINED3DTSS_BUMPENVMAT10          ,
7252     WINED3DTSS_BUMPENVMAT11          ,
7253     WINED3DTSS_COLORARG0             ,
7254     WINED3DTSS_COLORARG1             ,
7255     WINED3DTSS_COLORARG2             ,
7256     WINED3DTSS_COLOROP               ,
7257     WINED3DTSS_RESULTARG             ,
7258     WINED3DTSS_TEXCOORDINDEX         ,
7259     WINED3DTSS_TEXTURETRANSFORMFLAGS
7260 };
7261
7262 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7263     WINED3DSAMP_ADDRESSU         ,
7264     WINED3DSAMP_ADDRESSV         ,
7265     WINED3DSAMP_ADDRESSW         ,
7266     WINED3DSAMP_BORDERCOLOR      ,
7267     WINED3DSAMP_MAGFILTER        ,
7268     WINED3DSAMP_MINFILTER        ,
7269     WINED3DSAMP_MIPFILTER        ,
7270     WINED3DSAMP_MIPMAPLODBIAS    ,
7271     WINED3DSAMP_MAXMIPLEVEL      ,
7272     WINED3DSAMP_MAXANISOTROPY    ,
7273     WINED3DSAMP_SRGBTEXTURE      ,
7274     WINED3DSAMP_ELEMENTINDEX
7275 };
7276
7277 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7278     WINED3DRS_AMBIENT                       ,
7279     WINED3DRS_AMBIENTMATERIALSOURCE         ,
7280     WINED3DRS_CLIPPING                      ,
7281     WINED3DRS_CLIPPLANEENABLE               ,
7282     WINED3DRS_COLORVERTEX                   ,
7283     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
7284     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
7285     WINED3DRS_FOGDENSITY                    ,
7286     WINED3DRS_FOGEND                        ,
7287     WINED3DRS_FOGSTART                      ,
7288     WINED3DRS_FOGTABLEMODE                  ,
7289     WINED3DRS_FOGVERTEXMODE                 ,
7290     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
7291     WINED3DRS_LIGHTING                      ,
7292     WINED3DRS_LOCALVIEWER                   ,
7293     WINED3DRS_MULTISAMPLEANTIALIAS          ,
7294     WINED3DRS_MULTISAMPLEMASK               ,
7295     WINED3DRS_NORMALIZENORMALS              ,
7296     WINED3DRS_PATCHEDGESTYLE                ,
7297     WINED3DRS_POINTSCALE_A                  ,
7298     WINED3DRS_POINTSCALE_B                  ,
7299     WINED3DRS_POINTSCALE_C                  ,
7300     WINED3DRS_POINTSCALEENABLE              ,
7301     WINED3DRS_POINTSIZE                     ,
7302     WINED3DRS_POINTSIZE_MAX                 ,
7303     WINED3DRS_POINTSIZE_MIN                 ,
7304     WINED3DRS_POINTSPRITEENABLE             ,
7305     WINED3DRS_RANGEFOGENABLE                ,
7306     WINED3DRS_SPECULARMATERIALSOURCE        ,
7307     WINED3DRS_TWEENFACTOR                   ,
7308     WINED3DRS_VERTEXBLEND
7309 };
7310
7311 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7312     WINED3DTSS_TEXCOORDINDEX         ,
7313     WINED3DTSS_TEXTURETRANSFORMFLAGS
7314 };
7315
7316 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7317     WINED3DSAMP_DMAPOFFSET
7318 };