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