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