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