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