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