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