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