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