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