Move OpenQuery into msiquery.c and make it non-static.
[wine] / dlls / wined3d / device.c
1 /*
2  * IWineD3DDevice implementation
3  *
4  * Copyright 2002-2004 Jason Edmeades
5  * Copyright 2003-2004 Raphael Junqueira
6  * Copyright 2004 Christian Costa
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wined3d_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
27 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
30
31 /**********************************************************
32  * Global variable / Constants follow
33  **********************************************************/
34 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
35
36 /**********************************************************
37  * Utility functions follow
38  **********************************************************/
39 /* Convert the D3DLIGHT properties into equivalent gl lights */
40 void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
41
42     float quad_att;
43     float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
44     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
45
46     /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
47     glMatrixMode(GL_MODELVIEW);
48     glPushMatrix();
49     glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
50
51     /* Diffuse: */
52     colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
53     colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
54     colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
55     colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
56     glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
57     checkGLcall("glLightfv");
58
59     /* Specular */
60     colRGBA[0] = lightInfo->OriginalParms.Specular.r;
61     colRGBA[1] = lightInfo->OriginalParms.Specular.g;
62     colRGBA[2] = lightInfo->OriginalParms.Specular.b;
63     colRGBA[3] = lightInfo->OriginalParms.Specular.a;
64     glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
65     checkGLcall("glLightfv");
66
67     /* Ambient */
68     colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
69     colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
70     colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
71     colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
72     glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
73     checkGLcall("glLightfv");
74
75     /* Attenuation - Are these right? guessing... */
76     glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
77     checkGLcall("glLightf");
78     glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
79     checkGLcall("glLightf");
80
81     quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
82     if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
83     glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
84     checkGLcall("glLightf");
85
86     switch (lightInfo->OriginalParms.Type) {
87     case D3DLIGHT_POINT:
88         /* Position */
89         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
90         checkGLcall("glLightfv");
91         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
92         checkGLcall("glLightf");
93         /* FIXME: Range */
94         break;
95
96     case D3DLIGHT_SPOT:
97         /* Position */
98         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
99         checkGLcall("glLightfv");
100         /* Direction */
101         glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
102         checkGLcall("glLightfv");
103         glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
104         checkGLcall("glLightf");
105         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
106         checkGLcall("glLightf");
107         /* FIXME: Range */
108         break;
109
110     case D3DLIGHT_DIRECTIONAL:
111         /* Direction */
112         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
113         checkGLcall("glLightfv");
114         glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
115         checkGLcall("glLightf");
116         glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
117         checkGLcall("glLightf");
118         break;
119
120     default:
121         FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
122     }
123
124     /* Restore the modelview matrix */
125     glPopMatrix();
126 }
127
128 /* Apply the current values to the specified texture stage */
129 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
130     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
131     int i = 0;
132     float col[4];
133     BOOL changeTexture = TRUE;
134
135     TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
136     for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
137
138         BOOL skip = FALSE;
139
140         switch (i) {
141         /* Performance: For texture states where multiples effect the outcome, only bother
142               applying the last one as it will pick up all the other values                */
143         case D3DTSS_COLORARG0:  /* Will be picked up when setting color op */
144         case D3DTSS_COLORARG1:  /* Will be picked up when setting color op */
145         case D3DTSS_COLORARG2:  /* Will be picked up when setting color op */
146         case D3DTSS_ALPHAARG0:  /* Will be picked up when setting alpha op */
147         case D3DTSS_ALPHAARG1:  /* Will be picked up when setting alpha op */
148         case D3DTSS_ALPHAARG2:  /* Will be picked up when setting alpha op */
149            skip = TRUE;
150            break;
151
152         /* Performance: If the texture states only impact settings for the texture unit 
153              (compared to the texture object) then there is no need to reapply them. The
154              only time they need applying is the first time, since we cheat and put the  
155              values into the stateblock without applying.                                
156              Per-texture unit: texture function (eg. combine), ops and args
157                                texture env color                                               
158                                texture generation settings                               
159            Note: Due to some special conditions there may be a need to do particular ones
160              of these, which is what the Flags allows                                     */
161         case D3DTSS_COLOROP:       
162         case D3DTSS_TEXCOORDINDEX:
163             if (!(Flags == REAPPLY_ALL)) skip=TRUE;
164             break;
165
166         case D3DTSS_ALPHAOP:       
167             if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
168             break;
169
170         default:
171             skip = FALSE;
172         }
173
174         if (skip == FALSE) {
175            /* Performance: Only change to this texture if we have to */
176            if (changeTexture) {
177                /* Make appropriate texture active */
178                if (GL_SUPPORT(ARB_MULTITEXTURE)) {
179                    GLACTIVETEXTURE(Stage);
180                 } else if (Stage > 0) {
181                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
182                 }
183                 changeTexture = FALSE;
184            }
185
186            /* Now apply the change */
187            IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
188         }
189     }
190
191     /* Note the D3DRS value applies to all textures, but GL has one
192      *  per texture, so apply it now ready to be used!
193      */
194     D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[D3DRS_TEXTUREFACTOR], col);
195     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
196     checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
197
198     TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
199 }
200
201 /**********************************************************
202  * IWineD3DDevice implementation follows
203  **********************************************************/
204 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
205     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
206     *pParent = This->parent;
207     IUnknown_AddRef(This->parent);
208     return D3D_OK;
209 }
210
211 /*****
212  * Creation of other classes
213  *****/
214 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, 
215                              DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
216                              IUnknown *parent) {
217
218     IWineD3DVertexBufferImpl *object;
219     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
220
221     /* Allocate the storage for the device */
222     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DVertexBufferImpl));
223     if (NULL == object) {
224         *ppVertexBuffer = NULL;
225         return D3DERR_OUTOFVIDEOMEMORY;
226     }
227     object->lpVtbl                = &IWineD3DVertexBuffer_Vtbl;
228     object->resource.wineD3DDevice= This;
229     IWineD3DDevice_AddRef(iface);
230     object->resource.parent       = parent;
231     object->resource.resourceType = D3DRTYPE_VERTEXBUFFER;
232     object->resource.ref          = 1;
233     object->allocatedMemory       = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
234     object->currentDesc.Usage     = Usage;
235     object->currentDesc.Pool      = Pool;
236     object->currentDesc.FVF       = FVF;
237     object->currentDesc.Size      = Size;
238
239     TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
240     *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
241
242     return D3D_OK;
243 }
244
245 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage, 
246                                                     D3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
247                                                     HANDLE *sharedHandle, IUnknown *parent) {
248     IWineD3DIndexBufferImpl *object;
249     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
250
251     /* Allocate the storage for the device */
252     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DIndexBufferImpl));
253     if (NULL == object) {
254         *ppIndexBuffer = NULL;
255         return D3DERR_OUTOFVIDEOMEMORY;
256     }
257     object->lpVtbl = &IWineD3DIndexBuffer_Vtbl;
258     object->resource.wineD3DDevice = This;
259     IWineD3DDevice_AddRef(iface);
260     object->resource.resourceType  = D3DRTYPE_INDEXBUFFER;
261     object->resource.parent        = parent;
262     object->resource.ref = 1;
263     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
264     object->currentDesc.Usage = Usage;
265     object->currentDesc.Pool  = Pool;
266     object->currentDesc.Format= Format;
267     object->currentDesc.Size  = Length;
268
269     TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format, 
270                            debug_d3dformat(Format), Pool, object, object->allocatedMemory);
271     *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
272
273     return D3D_OK;
274 }
275
276 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
277   
278     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
279     IWineD3DStateBlockImpl *object;
280   
281     /* Allocate Storage for the state block */
282     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
283     if (NULL == object) {
284         *ppStateBlock = NULL;
285         return D3DERR_OUTOFVIDEOMEMORY;
286     }
287     object->lpVtbl        = &IWineD3DStateBlock_Vtbl;
288     object->wineD3DDevice = This;
289     IWineD3DDevice_AddRef(iface);
290     object->parent        = parent;
291     object->ref           = 1;
292     object->blockType     = Type;
293     *ppStateBlock         = (IWineD3DStateBlock *)object;
294
295     /* Special case - Used during initialization to produce a placeholder stateblock
296           so other functions called can update a state block                         */
297     if (Type == (D3DSTATEBLOCKTYPE) 0) {
298         /* Don't bother increasing the reference count otherwise a device will never
299            be freed due to circular dependencies                                   */
300         return D3D_OK;
301     }
302
303     /* Otherwise, might as well set the whole state block to the appropriate values */
304     IWineD3DDevice_AddRef(iface);
305     memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
306     FIXME("unfinished - needs to set up changed and set attributes\n");
307     return D3D_OK;
308 }
309
310 HRESULT WINAPI IWineD3DDeviceImpl_CreateRenderTarget(IWineD3DDevice *iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, 
311                                                      DWORD MultisampleQuality, BOOL Lockable, IWineD3DSurface** ppSurface, HANDLE* pSharedHandle, 
312                                                      IUnknown *parent) {
313     IWineD3DSurfaceImpl *object;
314     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
315     
316     object  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurfaceImpl));
317     if (NULL == object) {
318         *ppSurface = NULL;
319         return D3DERR_OUTOFVIDEOMEMORY;
320     }
321     object->lpVtbl                 = &IWineD3DSurface_Vtbl;
322     object->resource.wineD3DDevice = This;
323     IWineD3DDevice_AddRef(iface);
324     object->resource.resourceType  = D3DRTYPE_SURFACE;
325     object->resource.parent        = parent;
326     object->resource.ref           = 1;
327     *ppSurface = (IWineD3DSurface *)object;
328     object->container     = (IUnknown*) This;
329
330     object->currentDesc.Width  = Width;
331     object->currentDesc.Height = Height;
332     object->currentDesc.Format = Format;
333     object->currentDesc.Type   = D3DRTYPE_SURFACE;
334     object->currentDesc.Usage  = D3DUSAGE_RENDERTARGET;
335     object->currentDesc.Pool   = D3DPOOL_DEFAULT;
336     object->currentDesc.MultiSampleType = MultiSample;
337     object->bytesPerPixel = D3DFmtGetBpp(This, Format);
338     if (Format == D3DFMT_DXT1) { 
339         object->currentDesc_size = (Width * object->bytesPerPixel)/2 * Height;  /* DXT1 is half byte per pixel */
340     } else {
341         object->currentDesc_size = (Width * object->bytesPerPixel) * Height;
342     }
343     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->currentDesc_size);
344     object->lockable = Lockable;
345     object->locked = FALSE;
346     memset(&object->lockedRect, 0, sizeof(RECT));
347     IWineD3DSurface_CleanDirtyRect(*ppSurface);
348
349     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), Lockable, *ppSurface, object->allocatedMemory, object->currentDesc_size);
350     return D3D_OK;
351 }
352
353 HRESULT WINAPI IWineD3DDeviceImpl_CreateOffscreenPlainSurface(IWineD3DDevice *iface, 
354                                                UINT Width, UINT Height,
355                                                D3DFORMAT Format, D3DPOOL Pool, 
356                                                IWineD3DSurface** ppSurface,
357                                                HANDLE* pSharedHandle, IUnknown *parent) {
358
359     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
360     IWineD3DSurfaceImpl       *object;
361
362     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurfaceImpl));
363     if (NULL == object) {
364         *ppSurface = NULL;
365         return D3DERR_OUTOFVIDEOMEMORY;
366     }
367
368     object->lpVtbl = &IWineD3DSurface_Vtbl;
369     object->resource.wineD3DDevice = This;
370     IWineD3DDevice_AddRef(iface);
371     object->resource.resourceType  = D3DRTYPE_VOLUME;
372     object->resource.parent        = parent;
373     object->resource.ref           = 1;
374     *ppSurface = (IWineD3DSurface *)object;
375     object->container = (IUnknown*) This;
376
377     TRACE("(%p) : W(%d) H(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, 
378           Format, debug_d3dformat(Format), debug_d3dpool(Pool));
379
380     object->currentDesc.Width  = Width;
381     object->currentDesc.Height = Height;
382     object->currentDesc.Format = Format;
383     object->currentDesc.Type   = D3DRTYPE_SURFACE;
384     object->currentDesc.Usage  = 0;
385     object->currentDesc.Pool   = Pool;
386     object->bytesPerPixel      = D3DFmtGetBpp(This, Format);
387
388     /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
389        it is based around 4x4 pixel blocks it requires padding, so allocate enough
390        space!                                                                      */
391     if (Format == D3DFMT_DXT1) { 
392         object->currentDesc_size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
393     } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 || 
394                Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) { 
395         object->currentDesc_size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
396     } else {
397         object->currentDesc_size = (Width * object->bytesPerPixel) * Height;
398     }
399     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->currentDesc_size);
400     object->lockable = TRUE;
401     object->locked   = FALSE;
402     object->Dirty    = FALSE;
403     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), *ppSurface, object->allocatedMemory, object->currentDesc_size);
404     
405     memset(&object->lockedRect, 0, sizeof(RECT));
406     return IWineD3DSurface_CleanDirtyRect(*ppSurface);
407 }
408
409 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, 
410                                                 UINT Height, UINT Levels, DWORD Usage,
411                                                 D3DFORMAT Format, D3DPOOL Pool, 
412                                                 IWineD3DTexture** ppTexture, 
413                                                 HANDLE* pSharedHandle, IUnknown *parent,
414                                                 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
415
416     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
417     IWineD3DTextureImpl    *object;
418     unsigned int            i;
419     UINT                    tmpW;
420     UINT                    tmpH;
421
422     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DTextureImpl));
423     if (NULL == object) {
424         *ppTexture = NULL;
425         return D3DERR_OUTOFVIDEOMEMORY;
426     }
427
428     object->lpVtbl = &IWineD3DTexture_Vtbl;
429     object->resource.wineD3DDevice = This;
430     IWineD3DDevice_AddRef(iface);
431     object->resource.resourceType  = D3DRTYPE_TEXTURE;
432     object->resource.parent        = parent;
433     object->resource.ref           = 1;
434     *ppTexture = (IWineD3DTexture *)object;
435
436     TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, 
437           Width, Height, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
438     object->width  = Width;
439     object->height = Height;
440     object->usage  = Usage;
441     object->baseTexture.levels = Levels;
442     object->baseTexture.format = Format;
443
444     /* Calculate levels for mip mapping */
445     if (Levels == 0) {
446         object->baseTexture.levels++;
447         tmpW = Width;
448         tmpH = Height;
449         while (tmpW > 1 && tmpH > 1) {
450             tmpW = max(1, tmpW / 2);
451             tmpH = max(1, tmpH / 2);
452             object->baseTexture.levels++;
453         }
454         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
455     }
456
457     /* Generate all the surfaces */
458     tmpW = Width;
459     tmpH = Height;
460     for (i = 0; i < object->baseTexture.levels; i++) 
461     {
462         D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Pool, 
463                             (IWineD3DSurface **)&object->surfaces[i], pSharedHandle);
464         object->surfaces[i]->container = (IUnknown*) object;
465         object->surfaces[i]->currentDesc.Usage = Usage;
466         object->surfaces[i]->currentDesc.Pool = Pool;
467
468         /** 
469          * As written in msdn in IDirect3DTexture8::LockRect
470          *  Textures created in D3DPOOL_DEFAULT are not lockable.
471          */
472         if (D3DPOOL_DEFAULT == Pool) {
473             object->surfaces[i]->lockable = FALSE;
474         }
475
476         TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
477         tmpW = max(1, tmpW / 2);
478         tmpH = max(1, tmpH / 2);
479     }
480
481     *ppTexture = (IWineD3DTexture *) object;
482     TRACE("(%p) : Created texture %p\n", This, object);
483     return D3D_OK;
484 }
485
486 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface, 
487                                                       UINT Width, UINT Height, UINT Depth, 
488                                                       UINT Levels, DWORD Usage, 
489                                                       D3DFORMAT Format, D3DPOOL Pool, 
490                                                       IWineD3DVolumeTexture** ppVolumeTexture,
491                                                       HANDLE* pSharedHandle, IUnknown *parent,
492                                                       D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
493
494     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
495     IWineD3DVolumeTextureImpl *object;
496     unsigned int               i;
497     UINT                       tmpW;
498     UINT                       tmpH;
499     UINT                       tmpD;
500
501     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DVolumeTextureImpl));
502     if (NULL == object) {
503         *ppVolumeTexture = NULL;
504         return D3DERR_OUTOFVIDEOMEMORY;
505     }
506
507     object->lpVtbl = &IWineD3DVolumeTexture_Vtbl;
508     object->resource.wineD3DDevice = This;
509     IWineD3DDevice_AddRef(iface);
510     object->resource.resourceType  = D3DRTYPE_VOLUMETEXTURE;
511     object->resource.parent        = parent;
512     object->resource.ref           = 1;
513     *ppVolumeTexture = (IWineD3DVolumeTexture *)object;
514
515     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, 
516           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
517
518     object->width  = Width;
519     object->height = Height;
520     object->depth  = Depth;
521     object->usage  = Usage;
522     object->baseTexture.levels = Levels;
523     object->baseTexture.format = Format;
524
525     /* Calculate levels for mip mapping */
526     if (Levels == 0) {
527         object->baseTexture.levels++;
528         tmpW = Width;
529         tmpH = Height;
530         tmpD = Depth;
531         while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
532             tmpW = max(1, tmpW / 2);
533             tmpH = max(1, tmpH / 2);
534             tmpD = max(1, tmpD / 2);
535             object->baseTexture.levels++;
536         }
537         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
538     }
539
540     /* Generate all the surfaces */
541     tmpW = Width;
542     tmpH = Height;
543     tmpD = Depth;
544
545     for (i = 0; i < object->baseTexture.levels; i++) 
546     {
547         /* Create the volume - No entry point for this seperately?? */
548         D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage, 
549                            (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
550         object->volumes[i]->container = (IUnknown*) object;
551
552         tmpW = max(1, tmpW / 2);
553         tmpH = max(1, tmpH / 2);
554         tmpD = max(1, tmpD / 2);
555     }
556
557     *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
558     TRACE("(%p) : Created volume texture %p\n", This, object);
559     return D3D_OK;
560 }
561
562 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface, 
563                                                UINT Width, UINT Height, UINT Depth, 
564                                                DWORD Usage, 
565                                                D3DFORMAT Format, D3DPOOL Pool, 
566                                                IWineD3DVolume** ppVolume,
567                                                HANDLE* pSharedHandle, IUnknown *parent) {
568
569     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
570     IWineD3DVolumeImpl        *object;
571
572     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DVolumeImpl));
573     if (NULL == object) {
574         *ppVolume = NULL;
575         return D3DERR_OUTOFVIDEOMEMORY;
576     }
577
578     object->lpVtbl = &IWineD3DVolume_Vtbl;
579     object->wineD3DDevice = This;
580     IWineD3DDevice_AddRef(iface);
581     object->resourceType  = D3DRTYPE_VOLUME;
582     object->parent        = parent;
583     object->ref           = 1;
584     *ppVolume = (IWineD3DVolume *)object;
585
586     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, 
587           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
588
589     object->currentDesc.Width  = Width;
590     object->currentDesc.Height = Height;
591     object->currentDesc.Depth  = Depth;
592     object->currentDesc.Format = Format;
593     object->currentDesc.Type   = D3DRTYPE_VOLUME;
594     object->currentDesc.Pool   = Pool;
595     object->currentDesc.Usage  = Usage;
596     object->bytesPerPixel      = D3DFmtGetBpp(This, Format);
597
598     /* Note: Volume textures cannot be dxtn, hence no need to check here */
599     object->currentDesc.Size   = (Width * object->bytesPerPixel) * Height * Depth; 
600     object->allocatedMemory    = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->currentDesc.Size);
601     object->lockable = TRUE;
602     object->locked = FALSE;
603     memset(&object->lockedBox, 0, sizeof(D3DBOX));
604     object->dirty = FALSE;
605     return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
606 }
607
608 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength, 
609                                                     UINT Levels, DWORD Usage, 
610                                                     D3DFORMAT Format, D3DPOOL Pool, 
611                                                     IWineD3DCubeTexture** ppCubeTexture,
612                                                     HANDLE* pSharedHandle, IUnknown *parent,
613                                                     D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
614
615     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
616     IWineD3DCubeTextureImpl  *object;
617     unsigned int              i,j;
618     UINT                      tmpW;
619
620     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DCubeTextureImpl));
621     if (NULL == object) {
622         FIXME("Allocation of memory failed\n");
623         *ppCubeTexture = NULL;
624         return D3DERR_OUTOFVIDEOMEMORY;
625     }
626
627     object->lpVtbl = &IWineD3DCubeTexture_Vtbl;
628     object->resource.wineD3DDevice = This;
629     IWineD3DDevice_AddRef(iface);
630     object->resource.resourceType  = D3DRTYPE_CUBETEXTURE;
631     object->resource.parent        = parent;
632     object->resource.ref           = 1;
633     *ppCubeTexture = (IWineD3DCubeTexture *)object;
634
635     /* Allocate the storage for it */
636     TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, EdgeLength, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
637     
638     object->usage              = Usage;
639     object->edgeLength         = EdgeLength;
640     object->baseTexture.levels = Levels;
641     object->baseTexture.format = Format;
642
643     /* Calculate levels for mip mapping */
644     if (Levels == 0) {
645         object->baseTexture.levels++;
646         tmpW = EdgeLength;
647         while (tmpW > 1) {
648             tmpW = max(1, tmpW / 2);
649             object->baseTexture.levels++;
650         }
651         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
652     }
653
654     /* Generate all the surfaces */
655     tmpW = EdgeLength;
656     for (i = 0; i < object->baseTexture.levels; i++) {
657
658         /* Create the 6 faces */
659         for (j = 0; j < 6; j++) {
660
661             D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Pool, 
662                                 (IWineD3DSurface **)&object->surfaces[j][i], pSharedHandle);
663             object->surfaces[j][i]->container = (IUnknown*) object;
664             object->surfaces[j][i]->currentDesc.Usage = Usage;
665             object->surfaces[j][i]->currentDesc.Pool = Pool;
666
667             /** 
668              * As written in msdn in IDirect3DCubeTexture8::LockRect
669              *  Textures created in D3DPOOL_DEFAULT are not lockable.
670              */
671             if (D3DPOOL_DEFAULT == Pool) {
672               object->surfaces[j][i]->lockable = FALSE;
673             }
674
675             TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
676         }
677         tmpW = max(1, tmpW / 2);
678     }
679
680     TRACE("(%p) : Created Cube Texture %p\n", This, object);
681     *ppCubeTexture = (IWineD3DCubeTexture *) object;
682     return D3D_OK;
683 }
684
685 /*****
686  * Get / Set FVF
687  *****/
688 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
689     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
690
691     /* Update the current statte block */
692     This->updateStateBlock->fvf              = fvf;
693     This->updateStateBlock->changed.fvf      = TRUE;
694     This->updateStateBlock->set.fvf          = TRUE;
695
696     TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
697     
698     /* No difference if recording or not */
699     return D3D_OK;
700 }
701 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
702     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
703     TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
704     *pfvf = This->stateBlock->fvf;
705     return D3D_OK;
706 }
707
708 /*****
709  * Get / Set Stream Source
710  *****/
711 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
712     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
713     IWineD3DVertexBuffer     *oldSrc;
714
715     oldSrc = This->stateBlock->stream_source[StreamNumber];
716     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
717
718     This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
719     This->updateStateBlock->set.stream_source[StreamNumber]     = TRUE;
720     This->updateStateBlock->stream_stride[StreamNumber]         = Stride;
721     This->updateStateBlock->stream_source[StreamNumber]         = pStreamData;
722     This->updateStateBlock->stream_offset[StreamNumber]         = OffsetInBytes;
723
724     /* Handle recording of state blocks */
725     if (This->isRecordingState) {
726         TRACE("Recording... not performing anything\n");
727         return D3D_OK;
728     }
729
730     /* Not recording... */
731     if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
732     if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
733
734     return D3D_OK;
735 }
736
737 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
738     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
739
740     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
741     *pStream = This->stateBlock->stream_source[StreamNumber];
742     *pStride = This->stateBlock->stream_stride[StreamNumber];
743     *pOffset = This->stateBlock->stream_offset[StreamNumber];
744     IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
745     return D3D_OK;
746 }
747
748 /*****
749  * Get / Set & Multipy Transform
750  *****/
751 HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
752     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
753
754     /* Most of this routine, comments included copied from ddraw tree initially: */
755     TRACE("(%p) : Transform State=%d\n", This, d3dts);
756
757     /* Handle recording of state blocks */
758     if (This->isRecordingState) {
759         TRACE("Recording... not performing anything\n");
760         This->updateStateBlock->changed.transform[d3dts] = TRUE;
761         This->updateStateBlock->set.transform[d3dts]     = TRUE;
762         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
763         return D3D_OK;
764     }
765
766     /*
767      * If the new matrix is the same as the current one,
768      * we cut off any further processing. this seems to be a reasonable
769      * optimization because as was noticed, some apps (warcraft3 for example)
770      * tend towards setting the same matrix repeatedly for some reason.
771      *
772      * From here on we assume that the new matrix is different, wherever it matters.
773      */
774     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
775         TRACE("The app is setting the same matrix over again\n");
776         return D3D_OK;
777     } else {
778         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
779     }
780
781     /*
782        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
783        where ViewMat = Camera space, WorldMat = world space.
784
785        In OpenGL, camera and world space is combined into GL_MODELVIEW
786        matrix.  The Projection matrix stay projection matrix. 
787      */
788
789     /* Capture the times we can just ignore the change for now */
790     if (d3dts == D3DTS_WORLDMATRIX(0)) {
791         This->modelview_valid = FALSE;
792         return D3D_OK;
793
794     } else if (d3dts == D3DTS_PROJECTION) {
795         This->proj_valid = FALSE;
796         return D3D_OK;
797
798     } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { 
799         /* Indexed Vertex Blending Matrices 256 -> 511  */
800         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
801         FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
802         return D3D_OK;
803     } 
804     
805     /* Now we really are going to have to change a matrix */
806     ENTER_GL();
807
808     if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
809         if (d3dts < GL_LIMITS(textures)) {
810             int tex = d3dts - D3DTS_TEXTURE0;
811             GLACTIVETEXTURE(tex);
812             set_texture_matrix((float *)lpmatrix, 
813                                This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
814         }
815
816     } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
817         unsigned int k;
818
819         /* If we are changing the View matrix, reset the light and clipping planes to the new view   
820          * NOTE: We have to reset the positions even if the light/plane is not currently
821          *       enabled, since the call to enable it will not reset the position.                 
822          * NOTE2: Apparently texture transforms do NOT need reapplying
823          */
824         
825         PLIGHTINFOEL *lightChain = NULL;
826         This->modelview_valid = FALSE;
827         This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
828
829         glMatrixMode(GL_MODELVIEW);
830         checkGLcall("glMatrixMode(GL_MODELVIEW)");
831         glPushMatrix();
832         glLoadMatrixf((float *)lpmatrix);
833         checkGLcall("glLoadMatrixf(...)");
834
835         /* Reset lights */
836         lightChain = This->stateBlock->lights;
837         while (lightChain && lightChain->glIndex != -1) {
838             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
839             checkGLcall("glLightfv posn");
840             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
841             checkGLcall("glLightfv dirn");
842             lightChain = lightChain->next;
843         }
844
845         /* Reset Clipping Planes if clipping is enabled */
846         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
847             glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
848             checkGLcall("glClipPlane");
849         }
850         glPopMatrix();
851
852     } else { /* What was requested!?? */
853         WARN("invalid matrix specified: %i\n", d3dts);
854     }
855
856     /* Release lock, all done */
857     LEAVE_GL();
858     return D3D_OK;
859
860 }
861 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
862     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
863     TRACE("(%p) : for Transform State %d\n", This, State);
864     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
865     return D3D_OK;
866 }
867
868 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
869     D3DMATRIX *mat = NULL;
870     D3DMATRIX temp;
871
872     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
873      * below means it will be recorded in a state block change, but it
874      * works regardless where it is recorded. 
875      * If this is found to be wrong, change to StateBlock.
876      */
877     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
878     TRACE("(%p) : For state %u\n", This, State);
879
880     if (State < HIGHEST_TRANSFORMSTATE)
881     {
882         mat = &This->updateStateBlock->transforms[State];
883     } else {
884         FIXME("Unhandled transform state!!\n");
885     }
886
887     /* Copied from ddraw code:  */
888     temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
889     temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
890     temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
891     temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
892
893     temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
894     temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
895     temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
896     temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
897
898     temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
899     temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
900     temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
901     temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
902
903     temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
904     temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
905     temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
906     temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
907
908     /* Apply change via set transform - will reapply to eg. lights this way */
909     IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
910     return D3D_OK;
911 }
912
913 /*****
914  * Get / Set Light
915  *   WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
916  *****/
917 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
918    you can reference any indexes you want as long as that number max are enabled at any
919    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
920    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
921    but when recording, just build a chain pretty much of commands to be replayed.                  */
922    
923 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
924     float rho;
925     PLIGHTINFOEL *object, *temp;
926
927     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
928     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
929
930     /* If recording state block, just add to end of lights chain */
931     if (This->isRecordingState) {
932         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
933         if (NULL == object) {
934             return D3DERR_OUTOFVIDEOMEMORY;
935         }
936         memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
937         object->OriginalIndex = Index;
938         object->glIndex = -1;
939         object->changed = TRUE;
940
941         /* Add to the END of the chain of lights changes to be replayed */
942         if (This->updateStateBlock->lights == NULL) {
943             This->updateStateBlock->lights = object;
944         } else {
945             temp = This->updateStateBlock->lights;
946             while (temp->next != NULL) temp=temp->next;
947             temp->next = object;
948         }
949         TRACE("Recording... not performing anything more\n");
950         return D3D_OK;
951     }
952
953     /* Ok, not recording any longer so do real work */
954     object = This->stateBlock->lights;
955     while (object != NULL && object->OriginalIndex != Index) object = object->next;
956
957     /* If we didn't find it in the list of lights, time to add it */
958     if (object == NULL) {
959         PLIGHTINFOEL *insertAt,*prevPos;
960
961         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
962         if (NULL == object) {
963             return D3DERR_OUTOFVIDEOMEMORY;
964         }
965         object->OriginalIndex = Index;
966         object->glIndex = -1;
967
968         /* Add it to the front of list with the idea that lights will be changed as needed 
969            BUT after any lights currently assigned GL indexes                             */
970         insertAt = This->stateBlock->lights;
971         prevPos  = NULL;
972         while (insertAt != NULL && insertAt->glIndex != -1) {
973             prevPos  = insertAt;
974             insertAt = insertAt->next;
975         }
976
977         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
978             This->stateBlock->lights = object;
979         } else if (insertAt == NULL) { /* End of list */
980             prevPos->next = object;
981             object->prev = prevPos;
982         } else { /* Middle of chain */
983             if (prevPos == NULL) {
984                 This->stateBlock->lights = object;
985             } else {
986                 prevPos->next = object;
987             }
988             object->prev = prevPos;
989             object->next = insertAt;
990             insertAt->prev = object;
991         }
992     }
993
994     /* Initialze the object */
995     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,
996           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
997           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
998           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
999     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1000           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1001     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1002
1003     /* Save away the information */
1004     memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1005
1006     switch (pLight->Type) {
1007     case D3DLIGHT_POINT:
1008         /* Position */
1009         object->lightPosn[0] = pLight->Position.x;
1010         object->lightPosn[1] = pLight->Position.y;
1011         object->lightPosn[2] = pLight->Position.z;
1012         object->lightPosn[3] = 1.0f;
1013         object->cutoff = 180.0f;
1014         /* FIXME: Range */
1015         break;
1016
1017     case D3DLIGHT_DIRECTIONAL:
1018         /* Direction */
1019         object->lightPosn[0] = -pLight->Direction.x;
1020         object->lightPosn[1] = -pLight->Direction.y;
1021         object->lightPosn[2] = -pLight->Direction.z;
1022         object->lightPosn[3] = 0.0;
1023         object->exponent     = 0.0f;
1024         object->cutoff       = 180.0f;
1025         break;
1026
1027     case D3DLIGHT_SPOT:
1028         /* Position */
1029         object->lightPosn[0] = pLight->Position.x;
1030         object->lightPosn[1] = pLight->Position.y;
1031         object->lightPosn[2] = pLight->Position.z;
1032         object->lightPosn[3] = 1.0;
1033
1034         /* Direction */
1035         object->lightDirn[0] = pLight->Direction.x;
1036         object->lightDirn[1] = pLight->Direction.y;
1037         object->lightDirn[2] = pLight->Direction.z;
1038         object->lightDirn[3] = 1.0;
1039
1040         /*
1041          * opengl-ish and d3d-ish spot lights use too different models for the
1042          * light "intensity" as a function of the angle towards the main light direction,
1043          * so we only can approximate very roughly.
1044          * however spot lights are rather rarely used in games (if ever used at all).
1045          * furthermore if still used, probably nobody pays attention to such details.
1046          */
1047         if (pLight->Falloff == 0) {
1048             rho = 6.28f;
1049         } else {
1050             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1051         }
1052         if (rho < 0.0001) rho = 0.0001f;
1053         object->exponent = -0.3/log(cos(rho/2));
1054         object->cutoff = pLight->Phi*90/M_PI;
1055
1056         /* FIXME: Range */
1057         break;
1058
1059     default:
1060         FIXME("Unrecognized light type %d\n", pLight->Type);
1061     }
1062
1063     /* Update the live definitions if the light is currently assigned a glIndex */
1064     if (object->glIndex != -1) {
1065         setup_light(iface, object->glIndex, object);
1066     }
1067     return D3D_OK;
1068 }
1069
1070 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1071     PLIGHTINFOEL *lightInfo = NULL;
1072     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; 
1073     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1074     
1075     /* Locate the light in the live lights */
1076     lightInfo = This->stateBlock->lights;
1077     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1078
1079     if (lightInfo == NULL) {
1080         TRACE("Light information requested but light not defined\n");
1081         return D3DERR_INVALIDCALL;
1082     }
1083
1084     memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1085     return D3D_OK;
1086 }
1087
1088 /*****
1089  * Get / Set Light Enable 
1090  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1091  *****/
1092 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1093     PLIGHTINFOEL *lightInfo = NULL;
1094     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1095     TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1096
1097     /* If recording state block, just add to end of lights chain with changedEnable set to true */
1098     if (This->isRecordingState) {
1099         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1100         if (NULL == lightInfo) {
1101             return D3DERR_OUTOFVIDEOMEMORY;
1102         }
1103         lightInfo->OriginalIndex = Index;
1104         lightInfo->glIndex = -1;
1105         lightInfo->enabledChanged = TRUE;
1106
1107         /* Add to the END of the chain of lights changes to be replayed */
1108         if (This->updateStateBlock->lights == NULL) {
1109             This->updateStateBlock->lights = lightInfo;
1110         } else {
1111             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1112             while (temp->next != NULL) temp=temp->next;
1113             temp->next = lightInfo;
1114         }
1115         TRACE("Recording... not performing anything more\n");
1116         return D3D_OK;
1117     }
1118
1119     /* Not recording... So, locate the light in the live lights */
1120     lightInfo = This->stateBlock->lights;
1121     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1122
1123     /* Special case - enabling an undefined light creates one with a strict set of parms! */
1124     if (lightInfo == NULL) {
1125         D3DLIGHT9 lightParms;
1126         /* Warning - untested code :-) Prob safe to change fixme to a trace but
1127              wait until someone confirms it seems to work!                     */
1128         TRACE("Light enabled requested but light not defined, so defining one!\n"); 
1129         lightParms.Type = D3DLIGHT_DIRECTIONAL;
1130         lightParms.Diffuse.r = 1.0;
1131         lightParms.Diffuse.g = 1.0;
1132         lightParms.Diffuse.b = 1.0;
1133         lightParms.Diffuse.a = 0.0;
1134         lightParms.Specular.r = 0.0;
1135         lightParms.Specular.g = 0.0;
1136         lightParms.Specular.b = 0.0;
1137         lightParms.Specular.a = 0.0;
1138         lightParms.Ambient.r = 0.0;
1139         lightParms.Ambient.g = 0.0;
1140         lightParms.Ambient.b = 0.0;
1141         lightParms.Ambient.a = 0.0;
1142         lightParms.Position.x = 0.0;
1143         lightParms.Position.y = 0.0;
1144         lightParms.Position.z = 0.0;
1145         lightParms.Direction.x = 0.0;
1146         lightParms.Direction.y = 0.0;
1147         lightParms.Direction.z = 1.0;
1148         lightParms.Range = 0.0;
1149         lightParms.Falloff = 0.0;
1150         lightParms.Attenuation0 = 0.0;
1151         lightParms.Attenuation1 = 0.0;
1152         lightParms.Attenuation2 = 0.0;
1153         lightParms.Theta = 0.0;
1154         lightParms.Phi = 0.0;
1155         IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1156
1157         /* Search for it again! Should be fairly quick as near head of list */
1158         lightInfo = This->stateBlock->lights;
1159         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1160         if (lightInfo == NULL) {
1161             FIXME("Adding default lights has failed dismally\n");
1162             return D3DERR_INVALIDCALL;
1163         }
1164     }
1165
1166     /* OK, we now have a light... */
1167     if (Enable == FALSE) {
1168
1169         /* If we are disabling it, check it was enabled, and
1170            still only do something if it has assigned a glIndex (which it should have!)   */
1171         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1172             TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1173             ENTER_GL();
1174             glDisable(GL_LIGHT0 + lightInfo->glIndex);
1175             checkGLcall("glDisable GL_LIGHT0+Index");
1176             LEAVE_GL();
1177         } else {
1178             TRACE("Nothing to do as light was not enabled\n");
1179         }
1180         lightInfo->lightEnabled = FALSE;
1181     } else {
1182
1183         /* We are enabling it. If it is enabled, it's really simple */
1184         if (lightInfo->lightEnabled) {
1185             /* nop */
1186             TRACE("Nothing to do as light was enabled\n");
1187
1188         /* If it already has a glIndex, it's still simple */
1189         } else if (lightInfo->glIndex != -1) {
1190             TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1191             lightInfo->lightEnabled = TRUE;
1192             ENTER_GL();
1193             glEnable(GL_LIGHT0 + lightInfo->glIndex);
1194             checkGLcall("glEnable GL_LIGHT0+Index already setup");
1195             LEAVE_GL();
1196
1197         /* Otherwise got to find space - lights are ordered gl indexes first */
1198         } else {
1199             PLIGHTINFOEL *bsf  = NULL;
1200             PLIGHTINFOEL *pos  = This->stateBlock->lights;
1201             PLIGHTINFOEL *prev = NULL;
1202             int           Index= 0;
1203             int           glIndex = -1;
1204
1205             /* Try to minimize changes as much as possible */
1206             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1207
1208                 /* Try to remember which index can be replaced if necessary */
1209                 if (bsf==NULL && pos->lightEnabled == FALSE) {
1210                     /* Found a light we can replace, save as best replacement */
1211                     bsf = pos;
1212                 }
1213
1214                 /* Step to next space */
1215                 prev = pos;
1216                 pos = pos->next;
1217                 Index ++;
1218             }
1219
1220             /* If we have too many active lights, fail the call */
1221             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1222                 FIXME("Program requests too many concurrent lights\n");
1223                 return D3DERR_INVALIDCALL;
1224
1225             /* If we have allocated all lights, but not all are enabled,
1226                reuse one which is not enabled                           */
1227             } else if (Index == This->maxConcurrentLights) {
1228                 /* use bsf - Simply swap the new light and the BSF one */
1229                 PLIGHTINFOEL *bsfNext = bsf->next;
1230                 PLIGHTINFOEL *bsfPrev = bsf->prev;
1231
1232                 /* Sort out ends */
1233                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1234                 if (bsf->prev != NULL) {
1235                     bsf->prev->next = lightInfo;
1236                 } else {
1237                     This->stateBlock->lights = lightInfo;
1238                 }
1239
1240                 /* If not side by side, lots of chains to update */
1241                 if (bsf->next != lightInfo) {
1242                     lightInfo->prev->next = bsf;
1243                     bsf->next->prev = lightInfo;
1244                     bsf->next       = lightInfo->next;
1245                     bsf->prev       = lightInfo->prev;
1246                     lightInfo->next = bsfNext;
1247                     lightInfo->prev = bsfPrev;
1248
1249                 } else {
1250                     /* Simple swaps */
1251                     bsf->prev = lightInfo;
1252                     bsf->next = lightInfo->next;
1253                     lightInfo->next = bsf;
1254                     lightInfo->prev = bsfPrev;
1255                 }
1256
1257
1258                 /* Update states */
1259                 glIndex = bsf->glIndex;
1260                 bsf->glIndex = -1;
1261                 lightInfo->glIndex = glIndex;
1262                 lightInfo->lightEnabled = TRUE;
1263
1264                 /* Finally set up the light in gl itself */
1265                 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1266                 ENTER_GL();
1267                 setup_light(iface, glIndex, lightInfo);
1268                 glEnable(GL_LIGHT0 + glIndex);
1269                 checkGLcall("glEnable GL_LIGHT0 new setup");
1270                 LEAVE_GL();
1271
1272             /* If we reached the end of the allocated lights, with space in the
1273                gl lights, setup a new light                                     */
1274             } else if (pos->glIndex == -1) {
1275
1276                 /* We reached the end of the allocated gl lights, so already 
1277                     know the index of the next one!                          */
1278                 glIndex = Index;
1279                 lightInfo->glIndex = glIndex;
1280                 lightInfo->lightEnabled = TRUE;
1281
1282                 /* In an ideal world, it's already in the right place */
1283                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1284                    /* No need to move it */
1285                 } else {
1286                     /* Remove this light from the list */
1287                     lightInfo->prev->next = lightInfo->next;
1288                     if (lightInfo->next != NULL) {
1289                         lightInfo->next->prev = lightInfo->prev;
1290                     }
1291
1292                     /* Add in at appropriate place (inbetween prev and pos) */
1293                     lightInfo->prev = prev;
1294                     lightInfo->next = pos;
1295                     if (prev == NULL) {
1296                         This->stateBlock->lights = lightInfo;
1297                     } else {
1298                         prev->next = lightInfo;
1299                     }
1300                     if (pos != NULL) {
1301                         pos->prev = lightInfo;
1302                     }
1303                 }
1304
1305                 /* Finally set up the light in gl itself */
1306                 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1307                 ENTER_GL();
1308                 setup_light(iface, glIndex, lightInfo);
1309                 glEnable(GL_LIGHT0 + glIndex);
1310                 checkGLcall("glEnable GL_LIGHT0 new setup");
1311                 LEAVE_GL();
1312                 
1313             }
1314         }
1315     }
1316     return D3D_OK;
1317 }
1318
1319 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
1320
1321     PLIGHTINFOEL *lightInfo = NULL;
1322     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; 
1323     TRACE("(%p) : for idx(%ld)\n", This, Index);
1324     
1325     /* Locate the light in the live lights */
1326     lightInfo = This->stateBlock->lights;
1327     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1328
1329     if (lightInfo == NULL) {
1330         TRACE("Light enabled state requested but light not defined\n");
1331         return D3DERR_INVALIDCALL;
1332     }
1333     *pEnable = lightInfo->lightEnabled;
1334     return D3D_OK;
1335 }
1336
1337 /*****
1338  * Get / Set Clip Planes
1339  *****/
1340 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
1341     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1342     TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
1343
1344     /* Validate Index */
1345     if (Index >= GL_LIMITS(clipplanes)) {
1346         TRACE("Application has requested clipplane this device doesn't support\n");
1347         return D3DERR_INVALIDCALL;
1348     }
1349
1350     This->updateStateBlock->changed.clipplane[Index] = TRUE;
1351     This->updateStateBlock->set.clipplane[Index] = TRUE;
1352     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
1353     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
1354     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
1355     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
1356
1357     /* Handle recording of state blocks */
1358     if (This->isRecordingState) {
1359         TRACE("Recording... not performing anything\n");
1360         return D3D_OK;
1361     }
1362
1363     /* Apply it */
1364
1365     ENTER_GL();
1366
1367     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
1368     glMatrixMode(GL_MODELVIEW);
1369     glPushMatrix();
1370     glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1371
1372     TRACE("Clipplane [%f,%f,%f,%f]\n", 
1373           This->updateStateBlock->clipplane[Index][0], 
1374           This->updateStateBlock->clipplane[Index][1],
1375           This->updateStateBlock->clipplane[Index][2], 
1376           This->updateStateBlock->clipplane[Index][3]);
1377     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
1378     checkGLcall("glClipPlane");
1379
1380     glPopMatrix();
1381     LEAVE_GL();
1382
1383     return D3D_OK;
1384 }
1385
1386 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
1387     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1388     TRACE("(%p) : for idx %ld\n", This, Index);
1389
1390     /* Validate Index */
1391     if (Index >= GL_LIMITS(clipplanes)) {
1392         TRACE("Application has requested clipplane this device doesn't support\n");
1393         return D3DERR_INVALIDCALL;
1394     }
1395
1396     pPlane[0] = This->stateBlock->clipplane[Index][0];
1397     pPlane[1] = This->stateBlock->clipplane[Index][1];
1398     pPlane[2] = This->stateBlock->clipplane[Index][2];
1399     pPlane[3] = This->stateBlock->clipplane[Index][3];
1400     return D3D_OK;
1401 }
1402
1403 /*****
1404  * Get / Set Clip Plane Status
1405  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
1406  *****/
1407 HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
1408     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1409     FIXME("(%p) : stub\n", This);
1410     if (NULL == pClipStatus) {
1411       return D3DERR_INVALIDCALL;
1412     }
1413     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
1414     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
1415     return D3D_OK;
1416 }
1417
1418 HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
1419     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1420     FIXME("(%p) : stub\n", This);    
1421     if (NULL == pClipStatus) {
1422       return D3DERR_INVALIDCALL;
1423     }
1424     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
1425     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
1426     return D3D_OK;
1427 }
1428
1429 /*****
1430  * Get / Set Material
1431  *   WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
1432  *****/
1433 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
1434     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1435
1436     This->updateStateBlock->changed.material = TRUE;
1437     This->updateStateBlock->set.material = TRUE;
1438     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
1439
1440     /* Handle recording of state blocks */
1441     if (This->isRecordingState) {
1442         TRACE("Recording... not performing anything\n");
1443         return D3D_OK;
1444     }
1445
1446     ENTER_GL();
1447     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1448     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1449     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1450     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1451     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1452
1453     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
1454     checkGLcall("glMaterialfv");
1455     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
1456     checkGLcall("glMaterialfv");
1457
1458     /* Only change material color if specular is enabled, otherwise it is set to black */
1459     if (This->stateBlock->renderState[D3DRS_SPECULARENABLE]) {
1460        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1461        checkGLcall("glMaterialfv");
1462     } else {
1463        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1464        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1465        checkGLcall("glMaterialfv");
1466     }
1467     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
1468     checkGLcall("glMaterialfv");
1469     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
1470     checkGLcall("glMaterialf");
1471
1472     LEAVE_GL();
1473     return D3D_OK;
1474 }
1475
1476 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
1477     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1478     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
1479     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1480     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1481     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1482     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1483     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1484     return D3D_OK;
1485 }
1486
1487 /*****
1488  * Get / Set Indices
1489  *****/
1490 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData, 
1491                                              UINT BaseVertexIndex) {
1492     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
1493     IWineD3DIndexBuffer *oldIdxs;
1494
1495     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
1496     oldIdxs = This->updateStateBlock->pIndexData;
1497
1498     This->updateStateBlock->changed.indices = TRUE;
1499     This->updateStateBlock->set.indices = TRUE;
1500     This->updateStateBlock->pIndexData = pIndexData;
1501     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
1502
1503     /* Handle recording of state blocks */
1504     if (This->isRecordingState) {
1505         TRACE("Recording... not performing anything\n");
1506         return D3D_OK;
1507     }
1508
1509     if (oldIdxs)    IWineD3DIndexBuffer_Release(oldIdxs);
1510     if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
1511     return D3D_OK;
1512 }
1513
1514 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
1515     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1516
1517     *ppIndexData = This->stateBlock->pIndexData;
1518     
1519     /* up ref count on ppindexdata */
1520     if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
1521     *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
1522
1523     return D3D_OK;
1524 }
1525
1526 /*****
1527  * Get / Set Viewports
1528  *****/
1529 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
1530     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1531
1532     TRACE("(%p)\n", This);
1533     This->updateStateBlock->changed.viewport = TRUE;
1534     This->updateStateBlock->set.viewport = TRUE;
1535     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
1536
1537     /* Handle recording of state blocks */
1538     if (This->isRecordingState) {
1539         TRACE("Recording... not performing anything\n");
1540         return D3D_OK;
1541     }
1542
1543     ENTER_GL();
1544
1545     TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1546           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1547
1548     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1549     checkGLcall("glDepthRange");
1550
1551     /* Note: GL requires lower left, DirectX supplies upper left */
1552     glViewport(pViewport->X, (This->renderTarget->currentDesc.Height - (pViewport->Y + pViewport->Height)), 
1553                pViewport->Width, pViewport->Height);
1554     checkGLcall("glViewport");
1555
1556     LEAVE_GL();
1557
1558     return D3D_OK;
1559
1560 }
1561
1562 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
1563     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1564     TRACE("(%p)\n", This);
1565     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
1566     return D3D_OK;
1567 }
1568
1569 /*****
1570  * Get / Set Render States
1571  * TODO: Verify against dx9 definitions
1572  *****/
1573 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
1574
1575     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
1576     DWORD                OldValue = This->stateBlock->renderState[State];
1577     
1578     /* Simple way of referring to either a DWORD or a 4 byte float */
1579     union {
1580         DWORD d;
1581         float f;
1582     } tmpvalue;
1583         
1584     TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
1585     This->updateStateBlock->changed.renderState[State] = TRUE;
1586     This->updateStateBlock->set.renderState[State] = TRUE;
1587     This->updateStateBlock->renderState[State] = Value;
1588
1589     /* Handle recording of state blocks */
1590     if (This->isRecordingState) {
1591         TRACE("Recording... not performing anything\n");
1592         return D3D_OK;
1593     }
1594
1595     ENTER_GL();
1596
1597     switch (State) {
1598     case D3DRS_FILLMODE                  :
1599         switch ((D3DFILLMODE) Value) {
1600         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1601         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1602         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1603         default:
1604             FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
1605         }
1606         checkGLcall("glPolygonMode (fillmode)");
1607         break;
1608
1609     case D3DRS_LIGHTING                  :
1610         if (Value) {
1611             glEnable(GL_LIGHTING);
1612             checkGLcall("glEnable GL_LIGHTING");
1613         } else {
1614             glDisable(GL_LIGHTING);
1615             checkGLcall("glDisable GL_LIGHTING");
1616         }
1617         break;
1618
1619     case D3DRS_ZENABLE                   :
1620         switch ((D3DZBUFFERTYPE) Value) {
1621         case D3DZB_FALSE:
1622             glDisable(GL_DEPTH_TEST);
1623             checkGLcall("glDisable GL_DEPTH_TEST");
1624             break;
1625         case D3DZB_TRUE:
1626             glEnable(GL_DEPTH_TEST);
1627             checkGLcall("glEnable GL_DEPTH_TEST");
1628             break;
1629         case D3DZB_USEW:
1630             glEnable(GL_DEPTH_TEST);
1631             checkGLcall("glEnable GL_DEPTH_TEST");
1632             FIXME("W buffer is not well handled\n");
1633             break;
1634         default:
1635             FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
1636         }
1637         break;
1638
1639     case D3DRS_CULLMODE                  :
1640
1641         /* If we are culling "back faces with clockwise vertices" then
1642            set front faces to be counter clockwise and enable culling  
1643            of back faces                                               */
1644         switch ((D3DCULL) Value) {
1645         case D3DCULL_NONE:
1646             glDisable(GL_CULL_FACE);
1647             checkGLcall("glDisable GL_CULL_FACE");
1648             break;
1649         case D3DCULL_CW:
1650             glEnable(GL_CULL_FACE);
1651             checkGLcall("glEnable GL_CULL_FACE");
1652             if (This->renderUpsideDown) {
1653                 glFrontFace(GL_CW);
1654                 checkGLcall("glFrontFace GL_CW");
1655             } else {
1656                 glFrontFace(GL_CCW);
1657                 checkGLcall("glFrontFace GL_CCW");
1658             }
1659             glCullFace(GL_BACK);
1660             break;
1661         case D3DCULL_CCW:
1662             glEnable(GL_CULL_FACE);
1663             checkGLcall("glEnable GL_CULL_FACE");
1664             if (This->renderUpsideDown) {
1665                 glFrontFace(GL_CCW); 
1666                 checkGLcall("glFrontFace GL_CCW");
1667             } else {
1668                 glFrontFace(GL_CW);
1669                 checkGLcall("glFrontFace GL_CW");
1670             }
1671             glCullFace(GL_BACK);
1672             break;
1673         default:
1674             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
1675         }
1676         break;
1677
1678     case D3DRS_SHADEMODE                 :
1679         switch ((D3DSHADEMODE) Value) {
1680         case D3DSHADE_FLAT:
1681             glShadeModel(GL_FLAT);
1682             checkGLcall("glShadeModel");
1683             break;
1684         case D3DSHADE_GOURAUD:
1685             glShadeModel(GL_SMOOTH);
1686             checkGLcall("glShadeModel");
1687             break;
1688         case D3DSHADE_PHONG:
1689             FIXME("D3DSHADE_PHONG isn't supported?\n");
1690
1691             LEAVE_GL();
1692             return D3DERR_INVALIDCALL;
1693         default:
1694             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
1695         }
1696         break;
1697
1698     case D3DRS_DITHERENABLE              :
1699         if (Value) {
1700             glEnable(GL_DITHER);
1701             checkGLcall("glEnable GL_DITHER");
1702         } else {
1703             glDisable(GL_DITHER);
1704             checkGLcall("glDisable GL_DITHER");
1705         }
1706         break;
1707
1708     case D3DRS_ZWRITEENABLE              :
1709         if (Value) {
1710             glDepthMask(1);
1711             checkGLcall("glDepthMask");
1712         } else {
1713             glDepthMask(0);
1714             checkGLcall("glDepthMask");
1715         }
1716         break;
1717
1718     case D3DRS_ZFUNC                     :
1719         {
1720             int glParm = GL_LESS;
1721
1722             switch ((D3DCMPFUNC) Value) {
1723             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
1724             case D3DCMP_LESS:          glParm=GL_LESS; break;
1725             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
1726             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
1727             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
1728             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
1729             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
1730             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
1731             default:
1732                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1733             }
1734             glDepthFunc(glParm);
1735             checkGLcall("glDepthFunc");
1736         }
1737         break;
1738
1739     case D3DRS_AMBIENT                   :
1740         {
1741             float col[4];
1742             D3DCOLORTOGLFLOAT4(Value, col);
1743             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
1744             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
1745             checkGLcall("glLightModel for MODEL_AMBIENT");
1746
1747         }
1748         break;
1749
1750     case D3DRS_ALPHABLENDENABLE          :
1751         if (Value) {
1752             glEnable(GL_BLEND);
1753             checkGLcall("glEnable GL_BLEND");
1754         } else {
1755             glDisable(GL_BLEND);
1756             checkGLcall("glDisable GL_BLEND");
1757         };
1758         break;
1759
1760     case D3DRS_SRCBLEND                  :
1761     case D3DRS_DESTBLEND                 :
1762         {
1763             int newVal = GL_ZERO;
1764             switch (Value) {
1765             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
1766             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
1767             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
1768             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
1769             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
1770             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
1771             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
1772             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
1773             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
1774             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
1775             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
1776
1777             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
1778                 This->srcBlend = newVal;
1779                 This->dstBlend = newVal;
1780                 break;
1781
1782             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
1783                 This->srcBlend = newVal;
1784                 This->dstBlend = newVal;
1785                 break;
1786             default:
1787                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
1788             }
1789
1790             if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
1791             if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
1792             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
1793             glBlendFunc(This->srcBlend, This->dstBlend);
1794
1795             checkGLcall("glBlendFunc");
1796         }
1797         break;
1798
1799     case D3DRS_ALPHATESTENABLE           :
1800         if (Value) {
1801             glEnable(GL_ALPHA_TEST);
1802             checkGLcall("glEnable GL_ALPHA_TEST");
1803         } else {
1804             glDisable(GL_ALPHA_TEST);
1805             checkGLcall("glDisable GL_ALPHA_TEST");
1806         }
1807         break;
1808
1809     case D3DRS_ALPHAFUNC                 :
1810         {
1811             int glParm = GL_LESS;
1812             float ref = ((float) This->stateBlock->renderState[D3DRS_ALPHAREF]) / 255.0f;
1813
1814             switch ((D3DCMPFUNC) Value) {
1815             case D3DCMP_NEVER:         glParm = GL_NEVER; break;
1816             case D3DCMP_LESS:          glParm = GL_LESS; break;
1817             case D3DCMP_EQUAL:         glParm = GL_EQUAL; break;
1818             case D3DCMP_LESSEQUAL:     glParm = GL_LEQUAL; break;
1819             case D3DCMP_GREATER:       glParm = GL_GREATER; break;
1820             case D3DCMP_NOTEQUAL:      glParm = GL_NOTEQUAL; break;
1821             case D3DCMP_GREATEREQUAL:  glParm = GL_GEQUAL; break;
1822             case D3DCMP_ALWAYS:        glParm = GL_ALWAYS; break;
1823             default:
1824                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1825             }
1826             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
1827             glAlphaFunc(glParm, ref);
1828             This->alphafunc = glParm;
1829             checkGLcall("glAlphaFunc");
1830         }
1831         break;
1832
1833     case D3DRS_ALPHAREF                  :
1834         {
1835             int glParm = This->alphafunc;
1836             float ref = 1.0f;
1837
1838             ref = ((float) Value) / 255.0f;
1839             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
1840             glAlphaFunc(glParm, ref);
1841             checkGLcall("glAlphaFunc");
1842         }
1843         break;
1844
1845     case D3DRS_CLIPPLANEENABLE           :
1846     case D3DRS_CLIPPING                  :
1847         {
1848             /* Ensure we only do the changed clip planes */
1849             DWORD enable  = 0xFFFFFFFF;
1850             DWORD disable = 0x00000000;
1851             
1852             /* If enabling / disabling all */
1853             if (State == D3DRS_CLIPPING) {
1854                 if (Value) {
1855                     enable  = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
1856                     disable = 0x00;
1857                 } else {
1858                     disable = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
1859                     enable  = 0x00;
1860                 }
1861             } else {
1862                 enable =   Value & ~OldValue;
1863                 disable = ~Value &  OldValue;
1864             }
1865             
1866             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
1867             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
1868             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
1869             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
1870             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
1871             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
1872             
1873             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
1874             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
1875             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
1876             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
1877             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
1878             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
1879
1880             /** update clipping status */
1881             if (enable) {
1882               This->stateBlock->clip_status.ClipUnion = 0;
1883               This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
1884             } else {
1885               This->stateBlock->clip_status.ClipUnion = 0;
1886               This->stateBlock->clip_status.ClipIntersection = 0;
1887             }
1888         }
1889         break;
1890
1891     case D3DRS_BLENDOP                   :
1892         {
1893             int glParm = GL_FUNC_ADD;
1894
1895             switch ((D3DBLENDOP) Value) {
1896             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
1897             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
1898             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
1899             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
1900             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
1901             default:
1902                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
1903             }
1904             TRACE("glBlendEquation(%x)\n", glParm);
1905             glBlendEquation(glParm);
1906             checkGLcall("glBlendEquation");
1907         }
1908         break;
1909
1910     case D3DRS_TEXTUREFACTOR             :
1911         {
1912             unsigned int i;
1913
1914             /* Note the texture color applies to all textures whereas 
1915                GL_TEXTURE_ENV_COLOR applies to active only */
1916             float col[4];
1917             D3DCOLORTOGLFLOAT4(Value, col);
1918             /* Set the default alpha blend color */
1919             glBlendColor(col[0], col[1], col[2], col[3]);
1920             checkGLcall("glBlendColor");
1921
1922             /* And now the default texture color as well */
1923             for (i = 0; i < GL_LIMITS(textures); i++) {
1924
1925                 /* Note the D3DRS value applies to all textures, but GL has one
1926                    per texture, so apply it now ready to be used!               */
1927                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1928                     GLACTIVETEXTURE(i);
1929                 } else if (i>0) {
1930                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1931                 }
1932
1933                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1934                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1935             }
1936         }
1937         break;
1938
1939     case D3DRS_SPECULARENABLE            : 
1940         {
1941             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
1942                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
1943                specular color. This is wrong:
1944                Separate specular color means the specular colour is maintained separately, whereas
1945                single color means it is merged in. However in both cases they are being used to
1946                some extent.
1947                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
1948                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
1949                   running 1.4 yet!
1950              */
1951               if (Value) {
1952                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1953                 checkGLcall("glMaterialfv");
1954                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1955                   glEnable(GL_COLOR_SUM_EXT);
1956                 } else {
1957                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
1958                 }
1959                 checkGLcall("glEnable(GL_COLOR_SUM)");
1960               } else {
1961                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1962
1963                 /* for the case of enabled lighting: */
1964                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1965                 checkGLcall("glMaterialfv");
1966
1967                 /* for the case of disabled lighting: */
1968                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1969                   glDisable(GL_COLOR_SUM_EXT);
1970                 } else {
1971                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
1972                 }
1973                 checkGLcall("glDisable(GL_COLOR_SUM)");
1974               }
1975         }
1976         break;
1977
1978     case D3DRS_STENCILENABLE             :
1979         if (Value) {
1980             glEnable(GL_STENCIL_TEST);
1981             checkGLcall("glEnable GL_STENCIL_TEST");
1982         } else {
1983             glDisable(GL_STENCIL_TEST);
1984             checkGLcall("glDisable GL_STENCIL_TEST");
1985         }
1986         break;
1987
1988     case D3DRS_STENCILFUNC               :
1989         {
1990            int glParm = GL_ALWAYS;
1991            int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
1992            GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
1993
1994            switch ((D3DCMPFUNC) Value) {
1995            case D3DCMP_NEVER:         glParm=GL_NEVER; break;
1996            case D3DCMP_LESS:          glParm=GL_LESS; break;
1997            case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
1998            case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
1999            case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2000            case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2001            case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2002            case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2003            default:
2004                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2005            }
2006            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2007            This->stencilfunc = glParm;
2008            glStencilFunc(glParm, ref, mask);
2009            checkGLcall("glStencilFunc");
2010         }
2011         break;
2012
2013     case D3DRS_STENCILREF                :
2014         {
2015            int glParm = This->stencilfunc;
2016            int ref = 0;
2017            GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
2018
2019            ref = Value;
2020            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2021            glStencilFunc(glParm, ref, mask);
2022            checkGLcall("glStencilFunc");
2023         }
2024         break;
2025
2026     case D3DRS_STENCILMASK               :
2027         {
2028            int glParm = This->stencilfunc;
2029            int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
2030            GLuint mask = Value;
2031
2032            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2033            glStencilFunc(glParm, ref, mask);
2034            checkGLcall("glStencilFunc");
2035         }
2036         break;
2037
2038     case D3DRS_STENCILFAIL               :
2039         {
2040             GLenum fail  ; 
2041             GLenum zpass ; 
2042             GLenum zfail ; 
2043
2044             fail = StencilOp(Value);
2045             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2046             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2047             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2048             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2049
2050             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2051             glStencilOp(fail, zfail, zpass);
2052             checkGLcall("glStencilOp(fail, zfail, zpass);");
2053         }
2054         break;
2055     case D3DRS_STENCILZFAIL              :
2056         {
2057             GLenum fail  ; 
2058             GLenum zpass ; 
2059             GLenum zfail ; 
2060
2061             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2062             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2063             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2064             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2065             zfail = StencilOp(Value);
2066
2067             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2068             glStencilOp(fail, zfail, zpass);
2069             checkGLcall("glStencilOp(fail, zfail, zpass);");
2070         }
2071         break;
2072     case D3DRS_STENCILPASS               :
2073         {
2074             GLenum fail  ; 
2075             GLenum zpass ; 
2076             GLenum zfail ; 
2077
2078             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2079             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2080             zpass = StencilOp(Value);
2081             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2082             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2083
2084             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2085             glStencilOp(fail, zfail, zpass);
2086             checkGLcall("glStencilOp(fail, zfail, zpass);");
2087         }
2088         break;
2089
2090     case D3DRS_STENCILWRITEMASK          :
2091         {
2092             glStencilMask(Value);
2093             TRACE("glStencilMask(%lu)\n", Value);
2094             checkGLcall("glStencilMask");
2095         }
2096         break;
2097
2098     case D3DRS_FOGENABLE                 :
2099         {
2100           if (Value/* && This->stateBlock->renderState[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2101                glEnable(GL_FOG);
2102                checkGLcall("glEnable GL_FOG");
2103             } else {
2104                glDisable(GL_FOG);
2105                checkGLcall("glDisable GL_FOG");
2106             }
2107         }
2108         break;
2109
2110     case D3DRS_RANGEFOGENABLE            :
2111         {
2112             if (Value) {
2113               TRACE("Enabled RANGEFOG");
2114             } else {
2115               TRACE("Disabled RANGEFOG");
2116             }
2117         }
2118         break;
2119
2120     case D3DRS_FOGCOLOR                  :
2121         {
2122             float col[4];
2123             D3DCOLORTOGLFLOAT4(Value, col);
2124             /* Set the default alpha blend color */
2125             glFogfv(GL_FOG_COLOR, &col[0]);
2126             checkGLcall("glFog GL_FOG_COLOR");
2127         }
2128         break;
2129
2130     case D3DRS_FOGTABLEMODE              :
2131         { 
2132           glHint(GL_FOG_HINT, GL_NICEST);
2133           switch (Value) {
2134           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2135           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2136           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2137           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2138           default:
2139             FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2140           }
2141           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2142             glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2143           }
2144         }
2145         break;
2146
2147     case D3DRS_FOGVERTEXMODE             :
2148         { 
2149           glHint(GL_FOG_HINT, GL_FASTEST);
2150           switch (Value) {
2151           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2152           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2153           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2154           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2155           default:
2156             FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2157           }
2158           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2159             glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2160           }
2161         }
2162         break;
2163
2164     case D3DRS_FOGSTART                  :
2165         {
2166             tmpvalue.d = Value;
2167             glFogfv(GL_FOG_START, &tmpvalue.f);
2168             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2169             TRACE("Fog Start == %f\n", tmpvalue.f);
2170         }
2171         break;
2172
2173     case D3DRS_FOGEND                    :
2174         {
2175             tmpvalue.d = Value;
2176             glFogfv(GL_FOG_END, &tmpvalue.f);
2177             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2178             TRACE("Fog End == %f\n", tmpvalue.f);
2179         }
2180         break;
2181
2182     case D3DRS_FOGDENSITY                :
2183         {
2184             tmpvalue.d = Value;
2185             glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2186             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2187         }
2188         break;
2189
2190     case D3DRS_VERTEXBLEND               :
2191         {
2192           This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2193           TRACE("Vertex Blending state to %ld\n",  Value);
2194         }
2195         break;
2196
2197     case D3DRS_TWEENFACTOR               :
2198         {
2199           tmpvalue.d = Value;
2200           This->updateStateBlock->tween_factor = tmpvalue.f;
2201           TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2202         }
2203         break;
2204
2205     case D3DRS_INDEXEDVERTEXBLENDENABLE  :
2206         {
2207           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2208         }
2209         break;
2210
2211     case D3DRS_COLORVERTEX               :
2212     case D3DRS_DIFFUSEMATERIALSOURCE     :
2213     case D3DRS_SPECULARMATERIALSOURCE    :
2214     case D3DRS_AMBIENTMATERIALSOURCE     :
2215     case D3DRS_EMISSIVEMATERIALSOURCE    :
2216         {
2217             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2218
2219             if (This->stateBlock->renderState[D3DRS_COLORVERTEX]) {
2220                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2221                       This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE],
2222                       This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE],
2223                       This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE],
2224                       This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE]);
2225
2226                 if (This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2227                     if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2228                         Parm = GL_AMBIENT_AND_DIFFUSE;
2229                     } else {
2230                         Parm = GL_DIFFUSE;
2231                     }
2232                 } else if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2233                     Parm = GL_AMBIENT;
2234                 } else if (This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2235                     Parm = GL_EMISSION;
2236                 } else if (This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2237                     Parm = GL_SPECULAR;
2238                 } else {
2239                     Parm = -1;
2240                 }
2241
2242                 if (Parm == -1) {
2243                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2244                 } else {
2245                     This->tracking_color = NEEDS_TRACKING;
2246                     This->tracking_parm  = Parm;
2247                 }
2248
2249             } else {
2250                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2251             }
2252         }
2253         break; 
2254
2255     case D3DRS_LINEPATTERN               :
2256         {
2257             union {
2258                 DWORD                 d;
2259                 D3DLINEPATTERN        lp;
2260             } tmppattern;
2261             tmppattern.d = Value;
2262
2263             TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2264
2265             if (tmppattern.lp.wRepeatFactor) {
2266                 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2267                 checkGLcall("glLineStipple(repeat, linepattern)");
2268                 glEnable(GL_LINE_STIPPLE);
2269                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2270             } else {
2271                 glDisable(GL_LINE_STIPPLE);
2272                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2273             }
2274         }
2275         break;
2276
2277     case D3DRS_ZBIAS                     :
2278         {
2279             if (Value) {
2280                 tmpvalue.d = Value;
2281                 TRACE("ZBias value %f\n", tmpvalue.f);
2282                 glPolygonOffset(0, -tmpvalue.f);
2283                 checkGLcall("glPolygonOffset(0, -Value)");
2284                 glEnable(GL_POLYGON_OFFSET_FILL);
2285                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2286                 glEnable(GL_POLYGON_OFFSET_LINE);
2287                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2288                 glEnable(GL_POLYGON_OFFSET_POINT);
2289                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2290             } else {
2291                 glDisable(GL_POLYGON_OFFSET_FILL);
2292                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2293                 glDisable(GL_POLYGON_OFFSET_LINE);
2294                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2295                 glDisable(GL_POLYGON_OFFSET_POINT);
2296                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2297             }
2298         }
2299         break;
2300
2301     case D3DRS_NORMALIZENORMALS          :
2302         if (Value) {
2303             glEnable(GL_NORMALIZE);
2304             checkGLcall("glEnable(GL_NORMALIZE);");
2305         } else {
2306             glDisable(GL_NORMALIZE);
2307             checkGLcall("glDisable(GL_NORMALIZE);");
2308         }
2309         break;
2310
2311     case D3DRS_POINTSIZE                 :
2312         tmpvalue.d = Value;
2313         TRACE("Set point size to %f\n", tmpvalue.f);
2314         glPointSize(tmpvalue.f);
2315         checkGLcall("glPointSize(...);");
2316         break;
2317
2318     case D3DRS_POINTSIZE_MIN             :
2319         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2320           tmpvalue.d = Value;
2321           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2322           checkGLcall("glPointParameterfEXT(...);");
2323         } else {
2324           FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2325         }
2326         break;
2327
2328     case D3DRS_POINTSIZE_MAX             :
2329         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2330           tmpvalue.d = Value;
2331           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2332           checkGLcall("glPointParameterfEXT(...);");
2333         } else {
2334           FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2335         }
2336         break;
2337
2338     case D3DRS_POINTSCALE_A              :
2339     case D3DRS_POINTSCALE_B              :
2340     case D3DRS_POINTSCALE_C              :
2341     case D3DRS_POINTSCALEENABLE          :
2342         {
2343             /* If enabled, supply the parameters, otherwise fall back to defaults */
2344             if (This->stateBlock->renderState[D3DRS_POINTSCALEENABLE]) {
2345                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2346                 att[0] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_A]);
2347                 att[1] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_B]);
2348                 att[2] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_C]);
2349
2350                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2351                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2352                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2353                 } else {
2354                   TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2355                 }
2356             } else {
2357                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2358                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2359                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2360                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2361                 } else {
2362                   TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2363                 }
2364             }
2365             break;
2366         }
2367
2368     case D3DRS_COLORWRITEENABLE          :
2369       {
2370         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n", 
2371               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
2372               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2373               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
2374               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0); 
2375         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE, 
2376                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2377                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE, 
2378                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2379         checkGLcall("glColorMask(...)");
2380       }
2381       break;
2382
2383     case D3DRS_LOCALVIEWER               :
2384       {
2385         GLint state = (Value) ? 1 : 0;
2386         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);        
2387         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2388       }
2389       break;
2390
2391     case D3DRS_LASTPIXEL                 :
2392       {
2393         if (Value) {
2394           TRACE("Last Pixel Drawing Enabled\n");  
2395         } else {
2396           FIXME("Last Pixel Drawing Disabled, not handled yet\n");  
2397         }
2398       }
2399       break;
2400
2401     case D3DRS_SOFTWAREVERTEXPROCESSING  :
2402       {
2403         if (Value) {
2404           TRACE("Software Processing Enabled\n");  
2405         } else {
2406           TRACE("Software Processing Disabled\n");  
2407         }
2408       }
2409       break;
2410
2411       /** not supported */
2412     case D3DRS_ZVISIBLE                  :
2413       {
2414         LEAVE_GL();
2415         return D3DERR_INVALIDCALL;
2416       }
2417
2418         /* Unhandled yet...! */
2419     case D3DRS_EDGEANTIALIAS             :
2420     case D3DRS_WRAP0                     :
2421     case D3DRS_WRAP1                     :
2422     case D3DRS_WRAP2                     :
2423     case D3DRS_WRAP3                     :
2424     case D3DRS_WRAP4                     :
2425     case D3DRS_WRAP5                     :
2426     case D3DRS_WRAP6                     :
2427     case D3DRS_WRAP7                     :
2428     case D3DRS_POINTSPRITEENABLE         :
2429     case D3DRS_MULTISAMPLEANTIALIAS      :
2430     case D3DRS_MULTISAMPLEMASK           :
2431     case D3DRS_PATCHEDGESTYLE            :
2432     case D3DRS_PATCHSEGMENTS             :
2433     case D3DRS_DEBUGMONITORTOKEN         :
2434     case D3DRS_POSITIONORDER             :
2435     case D3DRS_NORMALORDER               :
2436         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2437         FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2438         break;
2439     default:
2440         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2441     }
2442
2443     LEAVE_GL();
2444
2445     return D3D_OK;
2446 }
2447
2448 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
2449     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2450     TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
2451     *pValue = This->stateBlock->renderState[State];
2452     return D3D_OK;
2453 }
2454
2455
2456 /*****
2457  * Get / Set Texture Stage States
2458  * TODO: Verify against dx9 definitions
2459  *****/
2460 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
2461     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2462     union {
2463         float f;
2464         DWORD d;
2465     } tmpvalue;
2466
2467     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
2468    
2469     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
2470
2471     /* Reject invalid texture units */
2472     if (Stage >= GL_LIMITS(textures)) {
2473         TRACE("Attempt to access invalid texture rejected\n");
2474         return D3DERR_INVALIDCALL;
2475     }
2476
2477     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
2478     This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
2479     This->updateStateBlock->textureState[Stage][Type] = Value;
2480
2481     /* Handle recording of state blocks */
2482     if (This->isRecordingState) {
2483         TRACE("Recording... not performing anything\n");
2484         return D3D_OK;
2485     }
2486
2487     ENTER_GL();
2488
2489     /* Make appropriate texture active */
2490     VTRACE(("Activating appropriate texture state %ld\n", Stage));
2491     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2492         GLACTIVETEXTURE(Stage);
2493     } else if (Stage > 0) {
2494         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2495     }
2496
2497     switch (Type) {
2498
2499     case D3DTSS_MINFILTER             :
2500     case D3DTSS_MIPFILTER             :
2501         {
2502             DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
2503             DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
2504             GLint realVal = GL_LINEAR;
2505
2506             if (ValueMIN == D3DTEXF_NONE) {
2507               /* Doesn't really make sense - Windows just seems to disable
2508                  mipmapping when this occurs                              */
2509               FIXME("Odd - minfilter of none, just disabling mipmaps\n");
2510               realVal = GL_LINEAR;
2511             } else if (ValueMIN == D3DTEXF_POINT) {
2512                 /* GL_NEAREST_* */
2513               if (ValueMIP == D3DTEXF_NONE) {
2514                     realVal = GL_NEAREST;
2515                 } else if (ValueMIP == D3DTEXF_POINT) {
2516                     realVal = GL_NEAREST_MIPMAP_NEAREST;
2517                 } else if (ValueMIP == D3DTEXF_LINEAR) {
2518                     realVal = GL_NEAREST_MIPMAP_LINEAR;
2519                 } else {
2520                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2521                     realVal = GL_NEAREST;
2522                 }
2523             } else if (ValueMIN == D3DTEXF_LINEAR) {
2524                 /* GL_LINEAR_* */
2525                 if (ValueMIP == D3DTEXF_NONE) {
2526                     realVal = GL_LINEAR;
2527                 } else if (ValueMIP == D3DTEXF_POINT) {
2528                     realVal = GL_LINEAR_MIPMAP_NEAREST;
2529                 } else if (ValueMIP == D3DTEXF_LINEAR) {
2530                     realVal = GL_LINEAR_MIPMAP_LINEAR;
2531                 } else {
2532                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2533                     realVal = GL_LINEAR;
2534                 }
2535             } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
2536               if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2537                 if (ValueMIP == D3DTEXF_NONE) {
2538                   realVal = GL_LINEAR_MIPMAP_LINEAR;                  
2539                 } else if (ValueMIP == D3DTEXF_POINT) {
2540                   realVal = GL_LINEAR_MIPMAP_NEAREST;
2541                 } else if (ValueMIP == D3DTEXF_LINEAR) {
2542                     realVal = GL_LINEAR_MIPMAP_LINEAR;
2543                 } else {
2544                   FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2545                   realVal = GL_LINEAR;
2546                 }
2547               } else {
2548                 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
2549                 realVal = GL_LINEAR;
2550               }
2551             } else {
2552                 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
2553                 realVal = GL_LINEAR_MIPMAP_LINEAR;
2554             }
2555
2556             TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
2557             glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
2558             checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
2559             /**
2560              * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
2561              */
2562             if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
2563               glTexParameteri(This->stateBlock->textureDimensions[Stage], 
2564                               GL_TEXTURE_MAX_ANISOTROPY_EXT, 
2565                               This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2566               checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
2567             }
2568         }
2569         break;
2570
2571     case D3DTSS_MAGFILTER             :
2572       {
2573         DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
2574         GLint realVal = GL_NEAREST;
2575
2576         if (ValueMAG == D3DTEXF_POINT) {
2577           realVal = GL_NEAREST;
2578         } else if (ValueMAG == D3DTEXF_LINEAR) {
2579           realVal = GL_LINEAR;
2580         } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
2581           if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2582             realVal = GL_LINEAR;
2583           } else {
2584             FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
2585             realVal = GL_NEAREST;
2586           }
2587         } else {
2588           FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
2589           realVal = GL_NEAREST;
2590         }
2591         TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
2592         glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
2593         checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
2594         /**
2595          * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
2596          */
2597         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
2598           glTexParameteri(This->stateBlock->textureDimensions[Stage], 
2599                           GL_TEXTURE_MAX_ANISOTROPY_EXT, 
2600                           This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2601           checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
2602         }
2603       }
2604       break;
2605
2606     case D3DTSS_MAXMIPLEVEL           :
2607       {
2608         /**
2609          * Not really the same, but the more apprioprate than nothing
2610          */
2611         glTexParameteri(This->stateBlock->textureDimensions[Stage], 
2612                         GL_TEXTURE_BASE_LEVEL, 
2613                         This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
2614         checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
2615       }
2616       break;
2617
2618     case D3DTSS_MAXANISOTROPY         :
2619       {        
2620         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2621           glTexParameteri(This->stateBlock->textureDimensions[Stage], 
2622                           GL_TEXTURE_MAX_ANISOTROPY_EXT, 
2623                           This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2624           checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
2625         }
2626       }
2627       break;
2628
2629     case D3DTSS_MIPMAPLODBIAS         :
2630       {        
2631         if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2632           tmpvalue.d = Value;
2633           glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, 
2634                     GL_TEXTURE_LOD_BIAS_EXT,
2635                     tmpvalue.f);
2636           checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2637         }
2638       }
2639       break;
2640
2641     case D3DTSS_ALPHAOP               :
2642     case D3DTSS_COLOROP               :
2643         {
2644
2645             if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
2646                 /* TODO: Disable by making this and all later levels disabled */
2647                 glDisable(GL_TEXTURE_1D);
2648                 checkGLcall("Disable GL_TEXTURE_1D");
2649                 glDisable(GL_TEXTURE_2D);
2650                 checkGLcall("Disable GL_TEXTURE_2D");
2651                 glDisable(GL_TEXTURE_3D);
2652                 checkGLcall("Disable GL_TEXTURE_3D");
2653                 break; /* Don't bother setting the texture operations */
2654             } else {
2655                 /* Enable only the appropriate texture dimension */
2656                 if (Type == D3DTSS_COLOROP) {
2657                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2658                         glEnable(GL_TEXTURE_1D);
2659                         checkGLcall("Enable GL_TEXTURE_1D");
2660                     } else {
2661                         glDisable(GL_TEXTURE_1D);
2662                         checkGLcall("Disable GL_TEXTURE_1D");
2663                     } 
2664                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
2665                       if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
2666                         glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
2667                         checkGLcall("Enable GL_TEXTURE_2D");
2668                       } else {
2669                         glEnable(GL_TEXTURE_2D);
2670                         checkGLcall("Enable GL_TEXTURE_2D");
2671                       }
2672                     } else {
2673                         glDisable(GL_TEXTURE_2D);
2674                         checkGLcall("Disable GL_TEXTURE_2D");
2675                     }
2676                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
2677                         glEnable(GL_TEXTURE_3D);
2678                         checkGLcall("Enable GL_TEXTURE_3D");
2679                     } else {
2680                         glDisable(GL_TEXTURE_3D);
2681                         checkGLcall("Disable GL_TEXTURE_3D");
2682                     }
2683                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
2684                         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
2685                         checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
2686                     } else {
2687                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2688                         checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
2689                     }
2690                 }
2691             }
2692             /* Drop through... (Except disable case) */
2693         case D3DTSS_COLORARG0             :
2694         case D3DTSS_COLORARG1             :
2695         case D3DTSS_COLORARG2             :
2696         case D3DTSS_ALPHAARG0             :
2697         case D3DTSS_ALPHAARG1             :
2698         case D3DTSS_ALPHAARG2             :
2699             {
2700                 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 || 
2701                                    Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
2702                 if (isAlphaArg) {
2703                     set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
2704                                This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1], 
2705                                This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2], 
2706                                This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
2707                 } else {
2708                     set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
2709                                This->stateBlock->textureState[Stage][D3DTSS_COLORARG1], 
2710                                This->stateBlock->textureState[Stage][D3DTSS_COLORARG2], 
2711                                This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
2712                 }
2713             }
2714             break;
2715         }
2716
2717     case D3DTSS_ADDRESSU              :
2718     case D3DTSS_ADDRESSV              :
2719     case D3DTSS_ADDRESSW              :
2720         {
2721             GLint wrapParm = GL_REPEAT;
2722
2723             switch (Value) {
2724             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
2725             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;      
2726             case D3DTADDRESS_BORDER: 
2727               {
2728                 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2729                   wrapParm = GL_CLAMP_TO_BORDER_ARB; 
2730                 } else {
2731                   /* FIXME: Not right, but better */
2732                   FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
2733                   wrapParm = GL_REPEAT; 
2734                 }
2735               }
2736               break;
2737             case D3DTADDRESS_MIRROR: 
2738               {
2739                 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2740                   wrapParm = GL_MIRRORED_REPEAT_ARB;
2741                 } else {
2742                   /* Unsupported in OpenGL pre-1.4 */
2743                   FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
2744                   wrapParm = GL_REPEAT;
2745                 }
2746               }
2747               break;
2748             case D3DTADDRESS_MIRRORONCE: 
2749               {
2750                 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2751                   wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
2752                 } else {
2753                   FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
2754                   wrapParm = GL_REPEAT; 
2755                 }
2756               }
2757               break;
2758
2759             default:
2760                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
2761                 wrapParm = GL_REPEAT; 
2762             }
2763
2764             switch (Type) {
2765             case D3DTSS_ADDRESSU:
2766                 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2767                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
2768                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
2769                 break;
2770             case D3DTSS_ADDRESSV:
2771                 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2772                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
2773                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
2774                 break;
2775             case D3DTSS_ADDRESSW:
2776                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2777                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
2778                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
2779                 break;
2780             default: /* nop */
2781                       break; /** stupic compilator */
2782             }
2783         }
2784         break;
2785
2786     case D3DTSS_BORDERCOLOR           :
2787         {
2788             float col[4];
2789             D3DCOLORTOGLFLOAT4(Value, col);
2790             TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value); 
2791             glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
2792             checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
2793         }
2794         break;
2795
2796     case D3DTSS_TEXCOORDINDEX         :
2797         {
2798             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
2799
2800             /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include 
2801                   one flag, you can still specify an index value, which the system uses to 
2802                   determine the texture wrapping mode.  
2803                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2804                   means use the vertex position (camera-space) as the input texture coordinates 
2805                   for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render 
2806                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
2807                   to the TEXCOORDINDEX value */
2808           
2809             /** 
2810              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos 
2811              */
2812             switch (Value & 0xFFFF0000) {
2813             case D3DTSS_TCI_PASSTHRU:
2814               /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2815               glDisable(GL_TEXTURE_GEN_S);
2816               glDisable(GL_TEXTURE_GEN_T);
2817               glDisable(GL_TEXTURE_GEN_R);
2818               checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
2819               break;
2820
2821             case D3DTSS_TCI_CAMERASPACEPOSITION:
2822               /* CameraSpacePosition means use the vertex position, transformed to camera space, 
2823                  as the input texture coordinates for this stage's texture transformation. This 
2824                  equates roughly to EYE_LINEAR                                                  */
2825               {
2826                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2827                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2828                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2829                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2830                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2831
2832                 glMatrixMode(GL_MODELVIEW);
2833                 glPushMatrix();
2834                 glLoadIdentity();
2835                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2836                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2837                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2838                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2839                 glPopMatrix();
2840                 
2841                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2842                 glEnable(GL_TEXTURE_GEN_S);
2843                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2844                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2845                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2846                 glEnable(GL_TEXTURE_GEN_T);
2847                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2848                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2849                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2850                 glEnable(GL_TEXTURE_GEN_R);
2851                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2852                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2853                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2854               }
2855               break;
2856
2857             case D3DTSS_TCI_CAMERASPACENORMAL:
2858               {
2859                 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2860                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2861                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2862                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2863                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2864                   TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2865
2866                   glMatrixMode(GL_MODELVIEW);
2867                   glPushMatrix();
2868                   glLoadIdentity();
2869                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2870                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2871                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2872                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2873                   glPopMatrix();
2874                   
2875                   glEnable(GL_TEXTURE_GEN_S);
2876                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2877                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2878                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2879                   glEnable(GL_TEXTURE_GEN_T);
2880                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2881                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2882                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2883                   glEnable(GL_TEXTURE_GEN_R);
2884                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2885                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2886                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2887                 }
2888               }
2889               break;
2890
2891             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2892               {
2893                 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2894                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2895                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2896                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2897                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2898                   TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2899                   
2900                   glMatrixMode(GL_MODELVIEW);
2901                   glPushMatrix();
2902                   glLoadIdentity();
2903                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2904                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2905                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2906                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2907                   glPopMatrix();
2908                   
2909                   glEnable(GL_TEXTURE_GEN_S);
2910                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2911                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2912                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2913                   glEnable(GL_TEXTURE_GEN_T);
2914                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2915                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2916                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2917                   glEnable(GL_TEXTURE_GEN_R);
2918                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2919                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2920                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2921                 }
2922               }
2923               break;
2924
2925             /* Unhandled types: */
2926             default:
2927                 /* Todo: */
2928                 /* ? disable GL_TEXTURE_GEN_n ? */ 
2929                 glDisable(GL_TEXTURE_GEN_S);
2930                 glDisable(GL_TEXTURE_GEN_T);
2931                 glDisable(GL_TEXTURE_GEN_R);
2932                 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
2933                 break;
2934             }
2935         }
2936         break;
2937
2938         /* Unhandled */
2939     case D3DTSS_TEXTURETRANSFORMFLAGS :
2940         set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
2941         break; 
2942
2943     case D3DTSS_BUMPENVMAT00          :
2944     case D3DTSS_BUMPENVMAT01          :
2945         TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
2946         break;
2947     case D3DTSS_BUMPENVMAT10          :
2948     case D3DTSS_BUMPENVMAT11          :
2949         TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
2950         break;
2951
2952     case D3DTSS_BUMPENVLSCALE         :
2953       TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2954       break;
2955
2956     case D3DTSS_BUMPENVLOFFSET        :
2957       TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2958       break;
2959
2960     case D3DTSS_RESULTARG             :
2961       TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2962       break;
2963
2964     default:
2965         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
2966         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2967     }
2968
2969     LEAVE_GL();
2970
2971     return D3D_OK;
2972 }
2973
2974 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
2975     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2976     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
2977     *pValue = This->updateStateBlock->textureState[Stage][Type];
2978     return D3D_OK;
2979 }
2980
2981 /*****
2982  * Get / Set Texture 
2983  *****/
2984 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
2985
2986     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2987     IWineD3DBaseTexture   *oldTexture;
2988     BOOL                   reapplyStates = TRUE;
2989     DWORD                  reapplyFlags = 0;
2990     INT                    oldTextureDimensions = -1;
2991     D3DRESOURCETYPE        textureType;
2992
2993     oldTexture = This->updateStateBlock->textures[Stage];
2994     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
2995
2996     /* Reject invalid texture units */
2997     if (Stage >= GL_LIMITS(textures)) {
2998         TRACE("Attempt to access invalid texture rejected\n");
2999         return D3DERR_INVALIDCALL;
3000     }
3001
3002     This->updateStateBlock->set.textures[Stage] = TRUE;
3003     This->updateStateBlock->changed.textures[Stage] = TRUE;
3004     This->updateStateBlock->textures[Stage] = pTexture;
3005
3006     /* Handle recording of state blocks */
3007     if (This->isRecordingState) {
3008         TRACE("Recording... not performing anything\n");
3009         return D3D_OK;
3010     }
3011
3012     oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
3013
3014     ENTER_GL();
3015
3016     /* Make appropriate texture active */
3017     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3018         GLACTIVETEXTURE(Stage);
3019
3020     } else if (Stage>0) {
3021         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3022     }
3023
3024     /* Decrement the count of the previous texture */
3025     if (NULL != oldTexture) {
3026         IWineD3DBaseTexture_Release(oldTexture);
3027     }
3028
3029     if (NULL != pTexture) {
3030         IWineD3DBaseTexture_AddRef((IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage]);
3031
3032         /* Now setup the texture appropraitly */
3033         textureType = IWineD3DBaseTexture_GetType(pTexture);
3034
3035         if (textureType == D3DRTYPE_TEXTURE) {
3036
3037           if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3038             TRACE("Skipping setting texture as old == new\n");
3039             reapplyStates = FALSE;
3040
3041           } else {
3042
3043             /* Standard 2D texture */
3044             TRACE("Standard 2d texture\n");
3045             This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3046
3047             /* Load up the texture now */
3048             IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
3049           }
3050
3051         } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3052
3053           if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3054               TRACE("Skipping setting texture as old == new\n");
3055               reapplyStates = FALSE;
3056
3057           } else {
3058
3059               /* Standard 3D (volume) texture */
3060               TRACE("Standard 3d texture\n");
3061               This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3062
3063               /* Load up the texture now */
3064               IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
3065           }
3066
3067         } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3068
3069             if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3070                 TRACE("Skipping setting texture as old == new\n");
3071                 reapplyStates = FALSE;
3072
3073             } else {
3074
3075                 /* Standard Cube texture */
3076                 TRACE("Standard Cube texture\n");
3077                 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3078
3079                 /* Load up the texture now */
3080                 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
3081             }
3082
3083         } else {
3084             FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
3085         }
3086
3087     } else {
3088
3089         TRACE("Setting to no texture (ie default texture)\n");
3090         This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3091         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3092         checkGLcall("glBindTexture");
3093         TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3094     }
3095
3096     /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3097     if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
3098
3099        glDisable(oldTextureDimensions);
3100        checkGLcall("Disable oldTextureDimensions");
3101
3102        if (This->stateBlock->textureState[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3103           glEnable(This->updateStateBlock->textureDimensions[Stage]);
3104           checkGLcall("glEnable new texture dimensions");
3105        }
3106
3107        /* If Alpha arg1 is texture then handle the special case when there changes between a
3108           texture and no texture - See comments in set_tex_op                                  */
3109        if ((This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) && 
3110            (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
3111        {
3112            reapplyFlags |= REAPPLY_ALPHAOP;
3113        }
3114     }
3115
3116
3117     /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3118        a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3119     if (reapplyStates) {
3120        IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
3121     }
3122
3123     LEAVE_GL();   
3124     TRACE("Texture now fully setup\n");
3125
3126     return D3D_OK;
3127 }
3128
3129 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3130     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3131     TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
3132     *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
3133     if (*ppTexture)
3134         IWineD3DBaseTexture_AddRef(*ppTexture);
3135     return D3D_OK;
3136 }
3137
3138 /*****
3139  * Get Back Buffer
3140  *****/
3141 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, 
3142                                                 IWineD3DSurface** ppBackBuffer) {
3143     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3144     
3145     *ppBackBuffer = (IWineD3DSurface *) This->backBuffer;
3146     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3147
3148     if (BackBuffer > This->presentParms.BackBufferCount - 1) {
3149         FIXME("Only one backBuffer currently supported\n");
3150         return D3DERR_INVALIDCALL;
3151     }
3152
3153     /* Note inc ref on returned surface */
3154     IWineD3DSurface_AddRef(*ppBackBuffer);
3155
3156     return D3D_OK;
3157 }
3158
3159 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, D3DCAPS9* pCaps) {
3160     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3161     WARN("(%p) : stub, calling idirect3d for now\n", This);
3162     IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3163     return D3D_OK;
3164 }
3165
3166 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
3167     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3168     HDC                 hdc;
3169     int                 bpp = 0;
3170
3171     pMode->Width        = GetSystemMetrics(SM_CXSCREEN);
3172     pMode->Height       = GetSystemMetrics(SM_CYSCREEN);
3173     pMode->RefreshRate  = 85; /*FIXME: How to identify? */
3174
3175     hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
3176     bpp = GetDeviceCaps(hdc, BITSPIXEL);
3177     DeleteDC(hdc);
3178
3179     switch (bpp) {
3180     case  8: pMode->Format       = D3DFMT_R8G8B8; break;
3181     case 16: pMode->Format       = D3DFMT_R5G6B5; break;
3182     case 24: /*pMode->Format       = D3DFMT_R8G8B8; break; */
3183     case 32: pMode->Format       = D3DFMT_A8R8G8B8; break;
3184     default: 
3185        FIXME("Unrecognized display mode format\n");
3186        pMode->Format       = D3DFMT_UNKNOWN;
3187     }
3188
3189     FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, 
3190           pMode->Format, debug_d3dformat(pMode->Format));
3191     return D3D_OK;
3192 }
3193  
3194 /*****
3195  * Scene related functions
3196  *****/
3197 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
3198     /* At the moment we have no need for any functionality at the beginning
3199        of a scene                                                          */
3200     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3201     TRACE("(%p) : stub\n", This);
3202     return D3D_OK;
3203 }
3204
3205 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
3206     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3207     TRACE("(%p)\n", This);
3208
3209     ENTER_GL();
3210
3211     glFlush();
3212     checkGLcall("glFlush");
3213
3214     if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
3215
3216         /* If we are rendering to a texture (surface) then flag it as dirty.
3217            A surfaces container is either the appropriate texture or the device itself
3218               depending on how the surface was created.                                */
3219         if (This->renderTarget != NULL && ((IWineD3DDeviceImpl *)This->renderTarget->container != This)) {
3220
3221             IWineD3DBaseTexture *cont = (IWineD3DBaseTexture *)This->renderTarget->container;
3222             /** always dirtify for now. we must find a better way to see that surface have been modified */
3223             This->renderTarget->inPBuffer = TRUE;
3224             This->renderTarget->inTexture = FALSE;
3225             IWineD3DBaseTexture_SetDirty(cont, TRUE);
3226             IWineD3DBaseTexture_PreLoad(cont);
3227             This->renderTarget->inPBuffer = FALSE;
3228         }
3229     }
3230
3231     LEAVE_GL();
3232     return D3D_OK;
3233 }
3234
3235 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface, 
3236                                           CONST RECT* pSourceRect, CONST RECT* pDestRect, 
3237                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
3238     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3239     TRACE("(%p) Presenting the frame\n", This);
3240
3241     ENTER_GL();
3242
3243     if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
3244
3245     glXSwapBuffers(This->display, This->drawable);
3246     /* Don't call checkGLcall, as glGetError is not applicable here */
3247     
3248     TRACE("glXSwapBuffers called, Starting new frame\n");
3249
3250     /* FPS support */
3251     if (TRACE_ON(d3d_fps))
3252     {
3253         static long prev_time, frames;
3254
3255         DWORD time = GetTickCount();
3256         frames++;
3257         /* every 1.5 seconds */
3258         if (time - prev_time > 1500) {
3259             TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
3260             prev_time = time;
3261             frames = 0;
3262         }
3263     }
3264
3265 #if defined(FRAME_DEBUGGING)
3266 {
3267     if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
3268         if (!isOn) {
3269             isOn = TRUE;
3270             FIXME("Enabling D3D Trace\n");
3271             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
3272 #if defined(SHOW_FRAME_MAKEUP)
3273             FIXME("Singe Frame snapshots Starting\n");
3274             isDumpingFrames = TRUE;
3275             glClear(GL_COLOR_BUFFER_BIT);
3276 #endif
3277
3278 #if defined(SINGLE_FRAME_DEBUGGING)
3279         } else {
3280 #if defined(SHOW_FRAME_MAKEUP)
3281             FIXME("Singe Frame snapshots Finishing\n");
3282             isDumpingFrames = FALSE;
3283 #endif
3284             FIXME("Singe Frame trace complete\n");
3285             DeleteFileA("C:\\D3DTRACE");
3286             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3287 #endif
3288         }
3289     } else {
3290         if (isOn) {
3291             isOn = FALSE;
3292 #if defined(SHOW_FRAME_MAKEUP)
3293             FIXME("Singe Frame snapshots Finishing\n");
3294             isDumpingFrames = FALSE;
3295 #endif
3296             FIXME("Disabling D3D Trace\n");
3297             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3298         }
3299     }
3300 }
3301 #endif
3302
3303     LEAVE_GL();
3304     /* Although this is not strictly required, a simple demo showed this does occur
3305        on (at least non-debug) d3d                                                  */
3306     if (This->presentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
3307        IWineD3DDevice_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
3308     }
3309
3310     return D3D_OK;
3311 }
3312
3313 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects, 
3314                                         DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
3315     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3316
3317     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
3318       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
3319       when the depth-buffer format does not contain stencil buffer information, this method fails. */
3320     GLbitfield     glMask = 0;
3321     GLboolean      old_ztest;
3322     GLfloat        old_z_clear_value;
3323     GLint          old_stencil_clear_value;
3324     GLfloat        old_color_clear_value[4];
3325     unsigned int   i;
3326     CONST D3DRECT* curRect;
3327
3328     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
3329           Count, pRects, Flags, Z, Stencil);
3330
3331     ENTER_GL();
3332
3333     glEnable(GL_SCISSOR_TEST);
3334     checkGLcall("glEnable GL_SCISSOR_TEST");
3335
3336     if (Count > 0 && pRects) {
3337         curRect = pRects;
3338     } else {
3339         curRect = NULL;
3340     }
3341
3342     /* Only set the values up once, as they are not changing */
3343     if (Flags & D3DCLEAR_STENCIL) {        
3344         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
3345         glClearStencil(Stencil);
3346         checkGLcall("glClearStencil");
3347         glMask = glMask | GL_STENCIL_BUFFER_BIT;
3348         glStencilMask(0xFFFFFFFF);
3349     }
3350
3351     if (Flags & D3DCLEAR_ZBUFFER) {
3352         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
3353         glDepthMask(GL_TRUE); 
3354         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
3355         glClearDepth(Z);
3356         checkGLcall("glClearDepth");
3357         glMask = glMask | GL_DEPTH_BUFFER_BIT;
3358     }
3359
3360     if (Flags & D3DCLEAR_TARGET) {
3361         TRACE("Clearing screen with glClear to color %lx\n", Color);
3362         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
3363         glClearColor(((Color >> 16) & 0xFF) / 255.0f, 
3364                      ((Color >>  8) & 0xFF) / 255.0f,
3365                      ((Color >>  0) & 0xFF) / 255.0f, 
3366                      ((Color >> 24) & 0xFF) / 255.0f);
3367         checkGLcall("glClearColor");
3368
3369         /* Clear ALL colors! */
3370         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3371         glMask = glMask | GL_COLOR_BUFFER_BIT;
3372     }
3373
3374     /* Now process each rect in turn */
3375     for (i = 0; i < Count || i == 0; i++) {
3376
3377         if (curRect) {
3378             /* Note gl uses lower left, width/height */
3379             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
3380                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
3381                   curRect->x1, (This->renderTarget->currentDesc.Height - curRect->y2), 
3382                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3383             glScissor(curRect->x1, (This->renderTarget->currentDesc.Height - curRect->y2), 
3384                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3385             checkGLcall("glScissor");
3386         } else {
3387             glScissor(This->stateBlock->viewport.X, 
3388                       (This->renderTarget->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)), 
3389                       This->stateBlock->viewport.Width, 
3390                       This->stateBlock->viewport.Height);
3391             checkGLcall("glScissor");
3392         }
3393
3394         /* Clear the selected rectangle (or full screen) */
3395         glClear(glMask);
3396         checkGLcall("glClear");
3397
3398         /* Step to the next rectangle */
3399         if (curRect) curRect = curRect + sizeof(D3DRECT);
3400     }
3401
3402     /* Restore the old values (why..?) */
3403     if (Flags & D3DCLEAR_STENCIL) {
3404         glClearStencil(old_stencil_clear_value);
3405         glStencilMask(This->stateBlock->renderState[D3DRS_STENCILWRITEMASK]);
3406     }    
3407     if (Flags & D3DCLEAR_ZBUFFER) {
3408         glDepthMask(old_ztest);
3409         glClearDepth(old_z_clear_value);
3410     }
3411     if (Flags & D3DCLEAR_TARGET) {
3412         glClearColor(old_color_clear_value[0], 
3413                      old_color_clear_value[1],
3414                      old_color_clear_value[2], 
3415                      old_color_clear_value[3]);
3416         glColorMask(This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE, 
3417                     This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3418                     This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE, 
3419                     This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3420     }
3421
3422     glDisable(GL_SCISSOR_TEST);
3423     checkGLcall("glDisable");
3424     LEAVE_GL();
3425
3426     return D3D_OK;
3427 }
3428
3429 /*****
3430  * Drawing functions
3431  *****/
3432 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, 
3433                                                 UINT PrimitiveCount) {
3434
3435     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3436     This->stateBlock->streamIsUP = FALSE;
3437
3438     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, 
3439                                debug_d3dprimitivetype(PrimitiveType), 
3440                                StartVertex, PrimitiveCount);
3441     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3442
3443     return D3D_OK;
3444 }
3445
3446 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
3447 HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface, 
3448                                                            D3DPRIMITIVETYPE PrimitiveType,
3449                                                            INT baseVIndex, UINT minIndex,
3450                                                            UINT NumVertices,UINT startIndex,UINT primCount) {
3451
3452     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
3453     UINT                 idxStride = 2;
3454     IWineD3DIndexBuffer *pIB;
3455     D3DINDEXBUFFER_DESC  IdxBufDsc;
3456     
3457     pIB = This->stateBlock->pIndexData;
3458     This->stateBlock->streamIsUP = FALSE;
3459
3460     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This, 
3461           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3462           minIndex, NumVertices, startIndex, baseVIndex, primCount);
3463
3464     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
3465     if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3466         idxStride = 2;
3467     } else {
3468         idxStride = 4;
3469     }
3470
3471     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, 
3472                       startIndex, idxStride, 
3473                       ((IWineD3DIndexBufferImpl *) pIB)->allocatedMemory,
3474                       minIndex);
3475
3476     return D3D_OK;
3477 }
3478
3479 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3480                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
3481                                                     UINT VertexStreamZeroStride) {
3482     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3483
3484     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, 
3485              debug_d3dprimitivetype(PrimitiveType), 
3486              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3487
3488     if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
3489
3490     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
3491     This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData; 
3492     This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
3493     This->stateBlock->streamIsUP = TRUE;
3494     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3495     This->stateBlock->stream_stride[0] = 0;
3496     This->stateBlock->stream_source[0] = NULL;
3497
3498     /*stream zero settings set to null at end, as per the msdn */
3499     return D3D_OK;
3500 }
3501
3502 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3503                                                              UINT MinVertexIndex,
3504                                                              UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3505                                                              D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3506                                                              UINT VertexStreamZeroStride) {
3507     int                 idxStride;
3508     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3509
3510     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", 
3511              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3512              MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,  
3513              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3514
3515     if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
3516
3517     if (IndexDataFormat == D3DFMT_INDEX16) {
3518         idxStride = 2;
3519     } else {
3520         idxStride = 4;
3521     }
3522
3523     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
3524     This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
3525     This->stateBlock->streamIsUP = TRUE;
3526     This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
3527
3528     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
3529
3530     /* stream zero settings set to null at end as per the msdn */
3531     This->stateBlock->stream_source[0] = NULL;
3532     This->stateBlock->stream_stride[0] = 0;
3533     IWineD3DDevice_SetIndices(iface, NULL, 0);
3534
3535     return D3D_OK;
3536 }
3537
3538 /**********************************************************
3539  * IUnknown parts follows
3540  **********************************************************/
3541
3542 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
3543 {
3544     return E_NOINTERFACE;
3545 }
3546
3547 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
3548     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3549     ULONG refCount = InterlockedIncrement(&This->ref);
3550
3551     TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
3552     return refCount;
3553 }
3554
3555 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
3556     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3557     ULONG refCount = InterlockedDecrement(&This->ref);
3558
3559     TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
3560
3561     if (!refCount) {
3562         IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
3563         IWineD3D_Release(This->wineD3D);
3564         HeapFree(GetProcessHeap(), 0, This);
3565     }
3566     return refCount;
3567 }
3568
3569 /**********************************************************
3570  * IWineD3DDevice VTbl follows
3571  **********************************************************/
3572
3573 IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
3574 {
3575     IWineD3DDeviceImpl_QueryInterface,
3576     IWineD3DDeviceImpl_AddRef,
3577     IWineD3DDeviceImpl_Release,
3578     IWineD3DDeviceImpl_GetParent,
3579     IWineD3DDeviceImpl_CreateVertexBuffer,
3580     IWineD3DDeviceImpl_CreateIndexBuffer,
3581     IWineD3DDeviceImpl_CreateStateBlock,
3582     IWineD3DDeviceImpl_CreateRenderTarget,
3583     IWineD3DDeviceImpl_CreateOffscreenPlainSurface,
3584     IWineD3DDeviceImpl_CreateTexture,
3585     IWineD3DDeviceImpl_CreateVolumeTexture,
3586     IWineD3DDeviceImpl_CreateVolume,
3587     IWineD3DDeviceImpl_CreateCubeTexture,
3588
3589     IWineD3DDeviceImpl_SetFVF,
3590     IWineD3DDeviceImpl_GetFVF,
3591     IWineD3DDeviceImpl_SetStreamSource,
3592     IWineD3DDeviceImpl_GetStreamSource,
3593     IWineD3DDeviceImpl_SetTransform,
3594     IWineD3DDeviceImpl_GetTransform,
3595     IWineD3DDeviceImpl_MultiplyTransform,
3596     IWineD3DDeviceImpl_SetLight,
3597     IWineD3DDeviceImpl_GetLight,
3598     IWineD3DDeviceImpl_SetLightEnable,
3599     IWineD3DDeviceImpl_GetLightEnable,
3600     IWineD3DDeviceImpl_SetClipPlane,
3601     IWineD3DDeviceImpl_GetClipPlane,
3602     IWineD3DDeviceImpl_SetClipStatus,
3603     IWineD3DDeviceImpl_GetClipStatus,
3604     IWineD3DDeviceImpl_SetMaterial,
3605     IWineD3DDeviceImpl_GetMaterial,
3606     IWineD3DDeviceImpl_SetIndices,
3607     IWineD3DDeviceImpl_GetIndices,
3608     IWineD3DDeviceImpl_SetViewport,
3609     IWineD3DDeviceImpl_GetViewport,
3610     IWineD3DDeviceImpl_SetRenderState,
3611     IWineD3DDeviceImpl_GetRenderState,
3612     IWineD3DDeviceImpl_SetTextureStageState,
3613     IWineD3DDeviceImpl_GetTextureStageState,
3614     IWineD3DDeviceImpl_SetTexture,
3615     IWineD3DDeviceImpl_GetTexture,
3616
3617     IWineD3DDeviceImpl_GetBackBuffer,
3618     IWineD3DDeviceImpl_GetDeviceCaps,
3619     IWineD3DDeviceImpl_GetDisplayMode,
3620
3621     IWineD3DDeviceImpl_BeginScene,
3622     IWineD3DDeviceImpl_EndScene,
3623     IWineD3DDeviceImpl_Present,
3624     IWineD3DDeviceImpl_Clear,
3625
3626     IWineD3DDeviceImpl_DrawPrimitive,
3627     IWineD3DDeviceImpl_DrawIndexedPrimitive,
3628     IWineD3DDeviceImpl_DrawPrimitiveUP,
3629     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
3630
3631     IWineD3DDeviceImpl_SetupTextureStates
3632 };