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