- Add texture support for all the texture types for d3d9->wined3d.
[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         *ppCubeTexture = NULL;
623         return D3DERR_OUTOFVIDEOMEMORY;
624     }
625
626     object->lpVtbl = &IWineD3DCubeTexture_Vtbl;
627     object->resource.wineD3DDevice = This;
628     IWineD3DDevice_AddRef(iface);
629     object->resource.resourceType  = D3DRTYPE_CUBETEXTURE;
630     object->resource.parent        = parent;
631     object->resource.ref           = 1;
632     *ppCubeTexture = (IWineD3DCubeTexture *)object;
633
634     /* Allocate the storage for it */
635     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));
636     
637     object->usage              = Usage;
638     object->edgeLength         = EdgeLength;
639     object->baseTexture.levels = Levels;
640     object->baseTexture.format = Format;
641
642     /* Calculate levels for mip mapping */
643     if (Levels == 0) {
644         object->baseTexture.levels++;
645         tmpW = EdgeLength;
646         while (tmpW > 1) {
647             tmpW = max(1, tmpW / 2);
648             object->baseTexture.levels++;
649         }
650         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
651     }
652
653     /* Generate all the surfaces */
654     tmpW = EdgeLength;
655     for (i = 0; i < object->baseTexture.levels; i++) {
656
657         /* Create the 6 faces */
658         for (j = 0; j < 6; j++) {
659
660             D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Pool, 
661                                 (IWineD3DSurface **)&object->surfaces[j][i], pSharedHandle);
662             object->surfaces[j][i]->container = (IUnknown*) object;
663             object->surfaces[j][i]->currentDesc.Usage = Usage;
664             object->surfaces[j][i]->currentDesc.Pool = Pool;
665
666                 /** 
667                  * As written in msdn in IDirect3DCubeTexture8::LockRect
668                  *  Textures created in D3DPOOL_DEFAULT are not lockable.
669                  */
670                 if (D3DPOOL_DEFAULT == Pool) {
671                   object->surfaces[j][i]->lockable = FALSE;
672                 }
673
674             TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
675         }
676         tmpW = max(1, tmpW / 2);
677     }
678
679     TRACE("(%p) : Created Cube Texture %p\n", This, object);
680     *ppCubeTexture = (IWineD3DCubeTexture *) object;
681     return D3D_OK;
682 }
683
684 /*****
685  * Get / Set FVF
686  *****/
687 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
688     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
689
690     /* Update the current statte block */
691     This->updateStateBlock->fvf              = fvf;
692     This->updateStateBlock->changed.fvf      = TRUE;
693     This->updateStateBlock->set.fvf          = TRUE;
694
695     TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
696     
697     /* No difference if recording or not */
698     return D3D_OK;
699 }
700 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
701     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
702     TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
703     *pfvf = This->stateBlock->fvf;
704     return D3D_OK;
705 }
706
707 /*****
708  * Get / Set Stream Source
709  *****/
710 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
711     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
712     IWineD3DVertexBuffer     *oldSrc;
713
714     oldSrc = This->stateBlock->stream_source[StreamNumber];
715     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
716
717     This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
718     This->updateStateBlock->set.stream_source[StreamNumber]     = TRUE;
719     This->updateStateBlock->stream_stride[StreamNumber]         = Stride;
720     This->updateStateBlock->stream_source[StreamNumber]         = pStreamData;
721     This->updateStateBlock->stream_offset[StreamNumber]         = OffsetInBytes;
722
723     /* Handle recording of state blocks */
724     if (This->isRecordingState) {
725         TRACE("Recording... not performing anything\n");
726         return D3D_OK;
727     }
728
729     /* Not recording... */
730     if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
731     if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
732
733     return D3D_OK;
734 }
735
736 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
737     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
738
739     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
740     *pStream = This->stateBlock->stream_source[StreamNumber];
741     *pStride = This->stateBlock->stream_stride[StreamNumber];
742     *pOffset = This->stateBlock->stream_offset[StreamNumber];
743     IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
744     return D3D_OK;
745 }
746
747 /*****
748  * Get / Set & Multipy Transform
749  *****/
750 HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
751     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
752
753     /* Most of this routine, comments included copied from ddraw tree initially: */
754     TRACE("(%p) : Transform State=%d\n", This, d3dts);
755
756     /* Handle recording of state blocks */
757     if (This->isRecordingState) {
758         TRACE("Recording... not performing anything\n");
759         This->updateStateBlock->changed.transform[d3dts] = TRUE;
760         This->updateStateBlock->set.transform[d3dts]     = TRUE;
761         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
762         return D3D_OK;
763     }
764
765     /*
766      * If the new matrix is the same as the current one,
767      * we cut off any further processing. this seems to be a reasonable
768      * optimization because as was noticed, some apps (warcraft3 for example)
769      * tend towards setting the same matrix repeatedly for some reason.
770      *
771      * From here on we assume that the new matrix is different, wherever it matters.
772      */
773     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
774         TRACE("The app is setting the same matrix over again\n");
775         return D3D_OK;
776     } else {
777         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
778     }
779
780     /*
781        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
782        where ViewMat = Camera space, WorldMat = world space.
783
784        In OpenGL, camera and world space is combined into GL_MODELVIEW
785        matrix.  The Projection matrix stay projection matrix. 
786      */
787
788     /* Capture the times we can just ignore the change for now */
789     if (d3dts == D3DTS_WORLDMATRIX(0)) {
790         This->modelview_valid = FALSE;
791         return D3D_OK;
792
793     } else if (d3dts == D3DTS_PROJECTION) {
794         This->proj_valid = FALSE;
795         return D3D_OK;
796
797     } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { 
798         /* Indexed Vertex Blending Matrices 256 -> 511  */
799         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
800         FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
801         return D3D_OK;
802     } 
803     
804     /* Now we really are going to have to change a matrix */
805     ENTER_GL();
806
807     if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
808         if (d3dts < GL_LIMITS(textures)) {
809             int tex = d3dts - D3DTS_TEXTURE0;
810             GLACTIVETEXTURE(tex);
811             set_texture_matrix((float *)lpmatrix, 
812                                This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
813         }
814
815     } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
816         unsigned int k;
817
818         /* If we are changing the View matrix, reset the light and clipping planes to the new view   
819          * NOTE: We have to reset the positions even if the light/plane is not currently
820          *       enabled, since the call to enable it will not reset the position.                 
821          * NOTE2: Apparently texture transforms do NOT need reapplying
822          */
823         
824         PLIGHTINFOEL *lightChain = NULL;
825         This->modelview_valid = FALSE;
826         This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
827
828         glMatrixMode(GL_MODELVIEW);
829         checkGLcall("glMatrixMode(GL_MODELVIEW)");
830         glPushMatrix();
831         glLoadMatrixf((float *)lpmatrix);
832         checkGLcall("glLoadMatrixf(...)");
833
834         /* Reset lights */
835         lightChain = This->stateBlock->lights;
836         while (lightChain && lightChain->glIndex != -1) {
837             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
838             checkGLcall("glLightfv posn");
839             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
840             checkGLcall("glLightfv dirn");
841             lightChain = lightChain->next;
842         }
843
844         /* Reset Clipping Planes if clipping is enabled */
845         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
846             glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
847             checkGLcall("glClipPlane");
848         }
849         glPopMatrix();
850
851     } else { /* What was requested!?? */
852         WARN("invalid matrix specified: %i\n", d3dts);
853     }
854
855     /* Release lock, all done */
856     LEAVE_GL();
857     return D3D_OK;
858
859 }
860 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
861     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
862     TRACE("(%p) : for Transform State %d\n", This, State);
863     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
864     return D3D_OK;
865 }
866
867 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
868     D3DMATRIX *mat = NULL;
869     D3DMATRIX temp;
870
871     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
872      * below means it will be recorded in a state block change, but it
873      * works regardless where it is recorded. 
874      * If this is found to be wrong, change to StateBlock.
875      */
876     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
877     TRACE("(%p) : For state %u\n", This, State);
878
879     if (State < HIGHEST_TRANSFORMSTATE)
880     {
881         mat = &This->updateStateBlock->transforms[State];
882     } else {
883         FIXME("Unhandled transform state!!\n");
884     }
885
886     /* Copied from ddraw code:  */
887     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);
888     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);
889     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);
890     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);
891
892     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);
893     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);
894     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);
895     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);
896
897     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);
898     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);
899     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);
900     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);
901
902     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);
903     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);
904     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);
905     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);
906
907     /* Apply change via set transform - will reapply to eg. lights this way */
908     IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
909     return D3D_OK;
910 }
911
912 /*****
913  * Get / Set Light
914  *   WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
915  *****/
916 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
917    you can reference any indexes you want as long as that number max are enabled at any
918    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
919    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
920    but when recording, just build a chain pretty much of commands to be replayed.                  */
921    
922 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
923     float rho;
924     PLIGHTINFOEL *object, *temp;
925
926     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
927     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
928
929     /* If recording state block, just add to end of lights chain */
930     if (This->isRecordingState) {
931         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
932         if (NULL == object) {
933             return D3DERR_OUTOFVIDEOMEMORY;
934         }
935         memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
936         object->OriginalIndex = Index;
937         object->glIndex = -1;
938         object->changed = TRUE;
939
940         /* Add to the END of the chain of lights changes to be replayed */
941         if (This->updateStateBlock->lights == NULL) {
942             This->updateStateBlock->lights = object;
943         } else {
944             temp = This->updateStateBlock->lights;
945             while (temp->next != NULL) temp=temp->next;
946             temp->next = object;
947         }
948         TRACE("Recording... not performing anything more\n");
949         return D3D_OK;
950     }
951
952     /* Ok, not recording any longer so do real work */
953     object = This->stateBlock->lights;
954     while (object != NULL && object->OriginalIndex != Index) object = object->next;
955
956     /* If we didn't find it in the list of lights, time to add it */
957     if (object == NULL) {
958         PLIGHTINFOEL *insertAt,*prevPos;
959
960         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
961         if (NULL == object) {
962             return D3DERR_OUTOFVIDEOMEMORY;
963         }
964         object->OriginalIndex = Index;
965         object->glIndex = -1;
966
967         /* Add it to the front of list with the idea that lights will be changed as needed 
968            BUT after any lights currently assigned GL indexes                             */
969         insertAt = This->stateBlock->lights;
970         prevPos  = NULL;
971         while (insertAt != NULL && insertAt->glIndex != -1) {
972             prevPos  = insertAt;
973             insertAt = insertAt->next;
974         }
975
976         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
977             This->stateBlock->lights = object;
978         } else if (insertAt == NULL) { /* End of list */
979             prevPos->next = object;
980             object->prev = prevPos;
981         } else { /* Middle of chain */
982             if (prevPos == NULL) {
983                 This->stateBlock->lights = object;
984             } else {
985                 prevPos->next = object;
986             }
987             object->prev = prevPos;
988             object->next = insertAt;
989             insertAt->prev = object;
990         }
991     }
992
993     /* Initialze the object */
994     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,
995           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
996           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
997           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
998     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
999           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1000     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1001
1002     /* Save away the information */
1003     memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1004
1005     switch (pLight->Type) {
1006     case D3DLIGHT_POINT:
1007         /* Position */
1008         object->lightPosn[0] = pLight->Position.x;
1009         object->lightPosn[1] = pLight->Position.y;
1010         object->lightPosn[2] = pLight->Position.z;
1011         object->lightPosn[3] = 1.0f;
1012         object->cutoff = 180.0f;
1013         /* FIXME: Range */
1014         break;
1015
1016     case D3DLIGHT_DIRECTIONAL:
1017         /* Direction */
1018         object->lightPosn[0] = -pLight->Direction.x;
1019         object->lightPosn[1] = -pLight->Direction.y;
1020         object->lightPosn[2] = -pLight->Direction.z;
1021         object->lightPosn[3] = 0.0;
1022         object->exponent     = 0.0f;
1023         object->cutoff       = 180.0f;
1024         break;
1025
1026     case D3DLIGHT_SPOT:
1027         /* Position */
1028         object->lightPosn[0] = pLight->Position.x;
1029         object->lightPosn[1] = pLight->Position.y;
1030         object->lightPosn[2] = pLight->Position.z;
1031         object->lightPosn[3] = 1.0;
1032
1033         /* Direction */
1034         object->lightDirn[0] = pLight->Direction.x;
1035         object->lightDirn[1] = pLight->Direction.y;
1036         object->lightDirn[2] = pLight->Direction.z;
1037         object->lightDirn[3] = 1.0;
1038
1039         /*
1040          * opengl-ish and d3d-ish spot lights use too different models for the
1041          * light "intensity" as a function of the angle towards the main light direction,
1042          * so we only can approximate very roughly.
1043          * however spot lights are rather rarely used in games (if ever used at all).
1044          * furthermore if still used, probably nobody pays attention to such details.
1045          */
1046         if (pLight->Falloff == 0) {
1047             rho = 6.28f;
1048         } else {
1049             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1050         }
1051         if (rho < 0.0001) rho = 0.0001f;
1052         object->exponent = -0.3/log(cos(rho/2));
1053         object->cutoff = pLight->Phi*90/M_PI;
1054
1055         /* FIXME: Range */
1056         break;
1057
1058     default:
1059         FIXME("Unrecognized light type %d\n", pLight->Type);
1060     }
1061
1062     /* Update the live definitions if the light is currently assigned a glIndex */
1063     if (object->glIndex != -1) {
1064         setup_light(iface, object->glIndex, object);
1065     }
1066     return D3D_OK;
1067 }
1068
1069 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1070     PLIGHTINFOEL *lightInfo = NULL;
1071     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; 
1072     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1073     
1074     /* Locate the light in the live lights */
1075     lightInfo = This->stateBlock->lights;
1076     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1077
1078     if (lightInfo == NULL) {
1079         TRACE("Light information requested but light not defined\n");
1080         return D3DERR_INVALIDCALL;
1081     }
1082
1083     memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1084     return D3D_OK;
1085 }
1086
1087 /*****
1088  * Get / Set Light Enable 
1089  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1090  *****/
1091 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1092     PLIGHTINFOEL *lightInfo = NULL;
1093     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1094     TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1095
1096     /* If recording state block, just add to end of lights chain with changedEnable set to true */
1097     if (This->isRecordingState) {
1098         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1099         if (NULL == lightInfo) {
1100             return D3DERR_OUTOFVIDEOMEMORY;
1101         }
1102         lightInfo->OriginalIndex = Index;
1103         lightInfo->glIndex = -1;
1104         lightInfo->enabledChanged = TRUE;
1105
1106         /* Add to the END of the chain of lights changes to be replayed */
1107         if (This->updateStateBlock->lights == NULL) {
1108             This->updateStateBlock->lights = lightInfo;
1109         } else {
1110             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1111             while (temp->next != NULL) temp=temp->next;
1112             temp->next = lightInfo;
1113         }
1114         TRACE("Recording... not performing anything more\n");
1115         return D3D_OK;
1116     }
1117
1118     /* Not recording... So, locate the light in the live lights */
1119     lightInfo = This->stateBlock->lights;
1120     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1121
1122     /* Special case - enabling an undefined light creates one with a strict set of parms! */
1123     if (lightInfo == NULL) {
1124         D3DLIGHT9 lightParms;
1125         /* Warning - untested code :-) Prob safe to change fixme to a trace but
1126              wait until someone confirms it seems to work!                     */
1127         TRACE("Light enabled requested but light not defined, so defining one!\n"); 
1128         lightParms.Type = D3DLIGHT_DIRECTIONAL;
1129         lightParms.Diffuse.r = 1.0;
1130         lightParms.Diffuse.g = 1.0;
1131         lightParms.Diffuse.b = 1.0;
1132         lightParms.Diffuse.a = 0.0;
1133         lightParms.Specular.r = 0.0;
1134         lightParms.Specular.g = 0.0;
1135         lightParms.Specular.b = 0.0;
1136         lightParms.Specular.a = 0.0;
1137         lightParms.Ambient.r = 0.0;
1138         lightParms.Ambient.g = 0.0;
1139         lightParms.Ambient.b = 0.0;
1140         lightParms.Ambient.a = 0.0;
1141         lightParms.Position.x = 0.0;
1142         lightParms.Position.y = 0.0;
1143         lightParms.Position.z = 0.0;
1144         lightParms.Direction.x = 0.0;
1145         lightParms.Direction.y = 0.0;
1146         lightParms.Direction.z = 1.0;
1147         lightParms.Range = 0.0;
1148         lightParms.Falloff = 0.0;
1149         lightParms.Attenuation0 = 0.0;
1150         lightParms.Attenuation1 = 0.0;
1151         lightParms.Attenuation2 = 0.0;
1152         lightParms.Theta = 0.0;
1153         lightParms.Phi = 0.0;
1154         IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1155
1156         /* Search for it again! Should be fairly quick as near head of list */
1157         lightInfo = This->stateBlock->lights;
1158         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1159         if (lightInfo == NULL) {
1160             FIXME("Adding default lights has failed dismally\n");
1161             return D3DERR_INVALIDCALL;
1162         }
1163     }
1164
1165     /* OK, we now have a light... */
1166     if (Enable == FALSE) {
1167
1168         /* If we are disabling it, check it was enabled, and
1169            still only do something if it has assigned a glIndex (which it should have!)   */
1170         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1171             TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1172             ENTER_GL();
1173             glDisable(GL_LIGHT0 + lightInfo->glIndex);
1174             checkGLcall("glDisable GL_LIGHT0+Index");
1175             LEAVE_GL();
1176         } else {
1177             TRACE("Nothing to do as light was not enabled\n");
1178         }
1179         lightInfo->lightEnabled = FALSE;
1180     } else {
1181
1182         /* We are enabling it. If it is enabled, it's really simple */
1183         if (lightInfo->lightEnabled) {
1184             /* nop */
1185             TRACE("Nothing to do as light was enabled\n");
1186
1187         /* If it already has a glIndex, it's still simple */
1188         } else if (lightInfo->glIndex != -1) {
1189             TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1190             lightInfo->lightEnabled = TRUE;
1191             ENTER_GL();
1192             glEnable(GL_LIGHT0 + lightInfo->glIndex);
1193             checkGLcall("glEnable GL_LIGHT0+Index already setup");
1194             LEAVE_GL();
1195
1196         /* Otherwise got to find space - lights are ordered gl indexes first */
1197         } else {
1198             PLIGHTINFOEL *bsf  = NULL;
1199             PLIGHTINFOEL *pos  = This->stateBlock->lights;
1200             PLIGHTINFOEL *prev = NULL;
1201             int           Index= 0;
1202             int           glIndex = -1;
1203
1204             /* Try to minimize changes as much as possible */
1205             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1206
1207                 /* Try to remember which index can be replaced if necessary */
1208                 if (bsf==NULL && pos->lightEnabled == FALSE) {
1209                     /* Found a light we can replace, save as best replacement */
1210                     bsf = pos;
1211                 }
1212
1213                 /* Step to next space */
1214                 prev = pos;
1215                 pos = pos->next;
1216                 Index ++;
1217             }
1218
1219             /* If we have too many active lights, fail the call */
1220             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1221                 FIXME("Program requests too many concurrent lights\n");
1222                 return D3DERR_INVALIDCALL;
1223
1224             /* If we have allocated all lights, but not all are enabled,
1225                reuse one which is not enabled                           */
1226             } else if (Index == This->maxConcurrentLights) {
1227                 /* use bsf - Simply swap the new light and the BSF one */
1228                 PLIGHTINFOEL *bsfNext = bsf->next;
1229                 PLIGHTINFOEL *bsfPrev = bsf->prev;
1230
1231                 /* Sort out ends */
1232                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1233                 if (bsf->prev != NULL) {
1234                     bsf->prev->next = lightInfo;
1235                 } else {
1236                     This->stateBlock->lights = lightInfo;
1237                 }
1238
1239                 /* If not side by side, lots of chains to update */
1240                 if (bsf->next != lightInfo) {
1241                     lightInfo->prev->next = bsf;
1242                     bsf->next->prev = lightInfo;
1243                     bsf->next       = lightInfo->next;
1244                     bsf->prev       = lightInfo->prev;
1245                     lightInfo->next = bsfNext;
1246                     lightInfo->prev = bsfPrev;
1247
1248                 } else {
1249                     /* Simple swaps */
1250                     bsf->prev = lightInfo;
1251                     bsf->next = lightInfo->next;
1252                     lightInfo->next = bsf;
1253                     lightInfo->prev = bsfPrev;
1254                 }
1255
1256
1257                 /* Update states */
1258                 glIndex = bsf->glIndex;
1259                 bsf->glIndex = -1;
1260                 lightInfo->glIndex = glIndex;
1261                 lightInfo->lightEnabled = TRUE;
1262
1263                 /* Finally set up the light in gl itself */
1264                 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1265                 ENTER_GL();
1266                 setup_light(iface, glIndex, lightInfo);
1267                 glEnable(GL_LIGHT0 + glIndex);
1268                 checkGLcall("glEnable GL_LIGHT0 new setup");
1269                 LEAVE_GL();
1270
1271             /* If we reached the end of the allocated lights, with space in the
1272                gl lights, setup a new light                                     */
1273             } else if (pos->glIndex == -1) {
1274
1275                 /* We reached the end of the allocated gl lights, so already 
1276                     know the index of the next one!                          */
1277                 glIndex = Index;
1278                 lightInfo->glIndex = glIndex;
1279                 lightInfo->lightEnabled = TRUE;
1280
1281                 /* In an ideal world, it's already in the right place */
1282                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1283                    /* No need to move it */
1284                 } else {
1285                     /* Remove this light from the list */
1286                     lightInfo->prev->next = lightInfo->next;
1287                     if (lightInfo->next != NULL) {
1288                         lightInfo->next->prev = lightInfo->prev;
1289                     }
1290
1291                     /* Add in at appropriate place (inbetween prev and pos) */
1292                     lightInfo->prev = prev;
1293                     lightInfo->next = pos;
1294                     if (prev == NULL) {
1295                         This->stateBlock->lights = lightInfo;
1296                     } else {
1297                         prev->next = lightInfo;
1298                     }
1299                     if (pos != NULL) {
1300                         pos->prev = lightInfo;
1301                     }
1302                 }
1303
1304                 /* Finally set up the light in gl itself */
1305                 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1306                 ENTER_GL();
1307                 setup_light(iface, glIndex, lightInfo);
1308                 glEnable(GL_LIGHT0 + glIndex);
1309                 checkGLcall("glEnable GL_LIGHT0 new setup");
1310                 LEAVE_GL();
1311                 
1312             }
1313         }
1314     }
1315     return D3D_OK;
1316 }
1317
1318 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
1319
1320     PLIGHTINFOEL *lightInfo = NULL;
1321     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; 
1322     TRACE("(%p) : for idx(%ld)\n", This, Index);
1323     
1324     /* Locate the light in the live lights */
1325     lightInfo = This->stateBlock->lights;
1326     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1327
1328     if (lightInfo == NULL) {
1329         TRACE("Light enabled state requested but light not defined\n");
1330         return D3DERR_INVALIDCALL;
1331     }
1332     *pEnable = lightInfo->lightEnabled;
1333     return D3D_OK;
1334 }
1335
1336 /*****
1337  * Get / Set Clip Planes
1338  *****/
1339 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
1340     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1341     TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
1342
1343     /* Validate Index */
1344     if (Index >= GL_LIMITS(clipplanes)) {
1345         TRACE("Application has requested clipplane this device doesn't support\n");
1346         return D3DERR_INVALIDCALL;
1347     }
1348
1349     This->updateStateBlock->changed.clipplane[Index] = TRUE;
1350     This->updateStateBlock->set.clipplane[Index] = TRUE;
1351     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
1352     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
1353     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
1354     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
1355
1356     /* Handle recording of state blocks */
1357     if (This->isRecordingState) {
1358         TRACE("Recording... not performing anything\n");
1359         return D3D_OK;
1360     }
1361
1362     /* Apply it */
1363
1364     ENTER_GL();
1365
1366     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
1367     glMatrixMode(GL_MODELVIEW);
1368     glPushMatrix();
1369     glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1370
1371     TRACE("Clipplane [%f,%f,%f,%f]\n", 
1372           This->updateStateBlock->clipplane[Index][0], 
1373           This->updateStateBlock->clipplane[Index][1],
1374           This->updateStateBlock->clipplane[Index][2], 
1375           This->updateStateBlock->clipplane[Index][3]);
1376     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
1377     checkGLcall("glClipPlane");
1378
1379     glPopMatrix();
1380     LEAVE_GL();
1381
1382     return D3D_OK;
1383 }
1384
1385 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
1386     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1387     TRACE("(%p) : for idx %ld\n", This, Index);
1388
1389     /* Validate Index */
1390     if (Index >= GL_LIMITS(clipplanes)) {
1391         TRACE("Application has requested clipplane this device doesn't support\n");
1392         return D3DERR_INVALIDCALL;
1393     }
1394
1395     pPlane[0] = This->stateBlock->clipplane[Index][0];
1396     pPlane[1] = This->stateBlock->clipplane[Index][1];
1397     pPlane[2] = This->stateBlock->clipplane[Index][2];
1398     pPlane[3] = This->stateBlock->clipplane[Index][3];
1399     return D3D_OK;
1400 }
1401
1402 /*****
1403  * Get / Set Clip Plane Status
1404  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
1405  *****/
1406 HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
1407     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1408     FIXME("(%p) : stub\n", This);
1409     if (NULL == pClipStatus) {
1410       return D3DERR_INVALIDCALL;
1411     }
1412     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
1413     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
1414     return D3D_OK;
1415 }
1416
1417 HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
1418     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1419     FIXME("(%p) : stub\n", This);    
1420     if (NULL == pClipStatus) {
1421       return D3DERR_INVALIDCALL;
1422     }
1423     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
1424     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
1425     return D3D_OK;
1426 }
1427
1428 /*****
1429  * Get / Set Material
1430  *   WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
1431  *****/
1432 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
1433     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1434
1435     This->updateStateBlock->changed.material = TRUE;
1436     This->updateStateBlock->set.material = TRUE;
1437     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
1438
1439     /* Handle recording of state blocks */
1440     if (This->isRecordingState) {
1441         TRACE("Recording... not performing anything\n");
1442         return D3D_OK;
1443     }
1444
1445     ENTER_GL();
1446     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1447     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1448     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1449     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1450     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1451
1452     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
1453     checkGLcall("glMaterialfv");
1454     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
1455     checkGLcall("glMaterialfv");
1456
1457     /* Only change material color if specular is enabled, otherwise it is set to black */
1458     if (This->stateBlock->renderState[D3DRS_SPECULARENABLE]) {
1459        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1460        checkGLcall("glMaterialfv");
1461     } else {
1462        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1463        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1464        checkGLcall("glMaterialfv");
1465     }
1466     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
1467     checkGLcall("glMaterialfv");
1468     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
1469     checkGLcall("glMaterialf");
1470
1471     LEAVE_GL();
1472     return D3D_OK;
1473 }
1474
1475 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
1476     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1477     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
1478     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1479     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1480     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1481     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1482     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1483     return D3D_OK;
1484 }
1485
1486 /*****
1487  * Get / Set Indices
1488  *****/
1489 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData, 
1490                                              UINT BaseVertexIndex) {
1491     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
1492     IWineD3DIndexBuffer *oldIdxs;
1493
1494     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
1495     oldIdxs = This->updateStateBlock->pIndexData;
1496
1497     This->updateStateBlock->changed.indices = TRUE;
1498     This->updateStateBlock->set.indices = TRUE;
1499     This->updateStateBlock->pIndexData = pIndexData;
1500     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
1501
1502     /* Handle recording of state blocks */
1503     if (This->isRecordingState) {
1504         TRACE("Recording... not performing anything\n");
1505         return D3D_OK;
1506     }
1507
1508     if (oldIdxs)    IWineD3DIndexBuffer_Release(oldIdxs);
1509     if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
1510     return D3D_OK;
1511 }
1512
1513 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
1514     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1515
1516     *ppIndexData = This->stateBlock->pIndexData;
1517     
1518     /* up ref count on ppindexdata */
1519     if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
1520     *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
1521
1522     return D3D_OK;
1523 }
1524
1525 /*****
1526  * Get / Set Viewports
1527  *****/
1528 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
1529     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1530
1531     TRACE("(%p)\n", This);
1532     This->updateStateBlock->changed.viewport = TRUE;
1533     This->updateStateBlock->set.viewport = TRUE;
1534     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
1535
1536     /* Handle recording of state blocks */
1537     if (This->isRecordingState) {
1538         TRACE("Recording... not performing anything\n");
1539         return D3D_OK;
1540     }
1541
1542     ENTER_GL();
1543
1544     TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1545           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1546
1547     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1548     checkGLcall("glDepthRange");
1549
1550     /* Note: GL requires lower left, DirectX supplies upper left */
1551     glViewport(pViewport->X, (This->renderTarget->currentDesc.Height - (pViewport->Y + pViewport->Height)), 
1552                pViewport->Width, pViewport->Height);
1553     checkGLcall("glViewport");
1554
1555     LEAVE_GL();
1556
1557     return D3D_OK;
1558
1559 }
1560
1561 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
1562     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1563     TRACE("(%p)\n", This);
1564     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
1565     return D3D_OK;
1566 }
1567
1568 /*****
1569  * Get / Set Render States
1570  * TODO: Verify against dx9 definitions
1571  *****/
1572 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
1573
1574     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
1575     DWORD                OldValue = This->stateBlock->renderState[State];
1576     
1577     /* Simple way of referring to either a DWORD or a 4 byte float */
1578     union {
1579         DWORD d;
1580         float f;
1581     } tmpvalue;
1582         
1583     TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
1584     This->updateStateBlock->changed.renderState[State] = TRUE;
1585     This->updateStateBlock->set.renderState[State] = TRUE;
1586     This->updateStateBlock->renderState[State] = Value;
1587
1588     /* Handle recording of state blocks */
1589     if (This->isRecordingState) {
1590         TRACE("Recording... not performing anything\n");
1591         return D3D_OK;
1592     }
1593
1594     ENTER_GL();
1595
1596     switch (State) {
1597     case D3DRS_FILLMODE                  :
1598         switch ((D3DFILLMODE) Value) {
1599         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1600         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1601         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1602         default:
1603             FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
1604         }
1605         checkGLcall("glPolygonMode (fillmode)");
1606         break;
1607
1608     case D3DRS_LIGHTING                  :
1609         if (Value) {
1610             glEnable(GL_LIGHTING);
1611             checkGLcall("glEnable GL_LIGHTING");
1612         } else {
1613             glDisable(GL_LIGHTING);
1614             checkGLcall("glDisable GL_LIGHTING");
1615         }
1616         break;
1617
1618     case D3DRS_ZENABLE                   :
1619         switch ((D3DZBUFFERTYPE) Value) {
1620         case D3DZB_FALSE:
1621             glDisable(GL_DEPTH_TEST);
1622             checkGLcall("glDisable GL_DEPTH_TEST");
1623             break;
1624         case D3DZB_TRUE:
1625             glEnable(GL_DEPTH_TEST);
1626             checkGLcall("glEnable GL_DEPTH_TEST");
1627             break;
1628         case D3DZB_USEW:
1629             glEnable(GL_DEPTH_TEST);
1630             checkGLcall("glEnable GL_DEPTH_TEST");
1631             FIXME("W buffer is not well handled\n");
1632             break;
1633         default:
1634             FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
1635         }
1636         break;
1637
1638     case D3DRS_CULLMODE                  :
1639
1640         /* If we are culling "back faces with clockwise vertices" then
1641            set front faces to be counter clockwise and enable culling  
1642            of back faces                                               */
1643         switch ((D3DCULL) Value) {
1644         case D3DCULL_NONE:
1645             glDisable(GL_CULL_FACE);
1646             checkGLcall("glDisable GL_CULL_FACE");
1647             break;
1648         case D3DCULL_CW:
1649             glEnable(GL_CULL_FACE);
1650             checkGLcall("glEnable GL_CULL_FACE");
1651             if (This->renderUpsideDown) {
1652                 glFrontFace(GL_CW);
1653                 checkGLcall("glFrontFace GL_CW");
1654             } else {
1655                 glFrontFace(GL_CCW);
1656                 checkGLcall("glFrontFace GL_CCW");
1657             }
1658             glCullFace(GL_BACK);
1659             break;
1660         case D3DCULL_CCW:
1661             glEnable(GL_CULL_FACE);
1662             checkGLcall("glEnable GL_CULL_FACE");
1663             if (This->renderUpsideDown) {
1664                 glFrontFace(GL_CCW); 
1665                 checkGLcall("glFrontFace GL_CCW");
1666             } else {
1667                 glFrontFace(GL_CW);
1668                 checkGLcall("glFrontFace GL_CW");
1669             }
1670             glCullFace(GL_BACK);
1671             break;
1672         default:
1673             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
1674         }
1675         break;
1676
1677     case D3DRS_SHADEMODE                 :
1678         switch ((D3DSHADEMODE) Value) {
1679         case D3DSHADE_FLAT:
1680             glShadeModel(GL_FLAT);
1681             checkGLcall("glShadeModel");
1682             break;
1683         case D3DSHADE_GOURAUD:
1684             glShadeModel(GL_SMOOTH);
1685             checkGLcall("glShadeModel");
1686             break;
1687         case D3DSHADE_PHONG:
1688             FIXME("D3DSHADE_PHONG isn't supported?\n");
1689
1690             LEAVE_GL();
1691             return D3DERR_INVALIDCALL;
1692         default:
1693             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
1694         }
1695         break;
1696
1697     case D3DRS_DITHERENABLE              :
1698         if (Value) {
1699             glEnable(GL_DITHER);
1700             checkGLcall("glEnable GL_DITHER");
1701         } else {
1702             glDisable(GL_DITHER);
1703             checkGLcall("glDisable GL_DITHER");
1704         }
1705         break;
1706
1707     case D3DRS_ZWRITEENABLE              :
1708         if (Value) {
1709             glDepthMask(1);
1710             checkGLcall("glDepthMask");
1711         } else {
1712             glDepthMask(0);
1713             checkGLcall("glDepthMask");
1714         }
1715         break;
1716
1717     case D3DRS_ZFUNC                     :
1718         {
1719             int glParm = GL_LESS;
1720
1721             switch ((D3DCMPFUNC) Value) {
1722             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
1723             case D3DCMP_LESS:          glParm=GL_LESS; break;
1724             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
1725             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
1726             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
1727             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
1728             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
1729             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
1730             default:
1731                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1732             }
1733             glDepthFunc(glParm);
1734             checkGLcall("glDepthFunc");
1735         }
1736         break;
1737
1738     case D3DRS_AMBIENT                   :
1739         {
1740             float col[4];
1741             D3DCOLORTOGLFLOAT4(Value, col);
1742             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
1743             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
1744             checkGLcall("glLightModel for MODEL_AMBIENT");
1745
1746         }
1747         break;
1748
1749     case D3DRS_ALPHABLENDENABLE          :
1750         if (Value) {
1751             glEnable(GL_BLEND);
1752             checkGLcall("glEnable GL_BLEND");
1753         } else {
1754             glDisable(GL_BLEND);
1755             checkGLcall("glDisable GL_BLEND");
1756         };
1757         break;
1758
1759     case D3DRS_SRCBLEND                  :
1760     case D3DRS_DESTBLEND                 :
1761         {
1762             int newVal = GL_ZERO;
1763             switch (Value) {
1764             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
1765             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
1766             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
1767             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
1768             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
1769             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
1770             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
1771             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
1772             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
1773             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
1774             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
1775
1776             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
1777                 This->srcBlend = newVal;
1778                 This->dstBlend = newVal;
1779                 break;
1780
1781             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
1782                 This->srcBlend = newVal;
1783                 This->dstBlend = newVal;
1784                 break;
1785             default:
1786                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
1787             }
1788
1789             if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
1790             if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
1791             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
1792             glBlendFunc(This->srcBlend, This->dstBlend);
1793
1794             checkGLcall("glBlendFunc");
1795         }
1796         break;
1797
1798     case D3DRS_ALPHATESTENABLE           :
1799         if (Value) {
1800             glEnable(GL_ALPHA_TEST);
1801             checkGLcall("glEnable GL_ALPHA_TEST");
1802         } else {
1803             glDisable(GL_ALPHA_TEST);
1804             checkGLcall("glDisable GL_ALPHA_TEST");
1805         }
1806         break;
1807
1808     case D3DRS_ALPHAFUNC                 :
1809         {
1810             int glParm = GL_LESS;
1811             float ref = ((float) This->stateBlock->renderState[D3DRS_ALPHAREF]) / 255.0f;
1812
1813             switch ((D3DCMPFUNC) Value) {
1814             case D3DCMP_NEVER:         glParm = GL_NEVER; break;
1815             case D3DCMP_LESS:          glParm = GL_LESS; break;
1816             case D3DCMP_EQUAL:         glParm = GL_EQUAL; break;
1817             case D3DCMP_LESSEQUAL:     glParm = GL_LEQUAL; break;
1818             case D3DCMP_GREATER:       glParm = GL_GREATER; break;
1819             case D3DCMP_NOTEQUAL:      glParm = GL_NOTEQUAL; break;
1820             case D3DCMP_GREATEREQUAL:  glParm = GL_GEQUAL; break;
1821             case D3DCMP_ALWAYS:        glParm = GL_ALWAYS; break;
1822             default:
1823                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1824             }
1825             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
1826             glAlphaFunc(glParm, ref);
1827             This->alphafunc = glParm;
1828             checkGLcall("glAlphaFunc");
1829         }
1830         break;
1831
1832     case D3DRS_ALPHAREF                  :
1833         {
1834             int glParm = This->alphafunc;
1835             float ref = 1.0f;
1836
1837             ref = ((float) Value) / 255.0f;
1838             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
1839             glAlphaFunc(glParm, ref);
1840             checkGLcall("glAlphaFunc");
1841         }
1842         break;
1843
1844     case D3DRS_CLIPPLANEENABLE           :
1845     case D3DRS_CLIPPING                  :
1846         {
1847             /* Ensure we only do the changed clip planes */
1848             DWORD enable  = 0xFFFFFFFF;
1849             DWORD disable = 0x00000000;
1850             
1851             /* If enabling / disabling all */
1852             if (State == D3DRS_CLIPPING) {
1853                 if (Value) {
1854                     enable  = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
1855                     disable = 0x00;
1856                 } else {
1857                     disable = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
1858                     enable  = 0x00;
1859                 }
1860             } else {
1861                 enable =   Value & ~OldValue;
1862                 disable = ~Value &  OldValue;
1863             }
1864             
1865             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
1866             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
1867             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
1868             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
1869             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
1870             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
1871             
1872             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
1873             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
1874             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
1875             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
1876             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
1877             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
1878
1879             /** update clipping status */
1880             if (enable) {
1881               This->stateBlock->clip_status.ClipUnion = 0;
1882               This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
1883             } else {
1884               This->stateBlock->clip_status.ClipUnion = 0;
1885               This->stateBlock->clip_status.ClipIntersection = 0;
1886             }
1887         }
1888         break;
1889
1890     case D3DRS_BLENDOP                   :
1891         {
1892             int glParm = GL_FUNC_ADD;
1893
1894             switch ((D3DBLENDOP) Value) {
1895             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
1896             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
1897             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
1898             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
1899             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
1900             default:
1901                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
1902             }
1903             TRACE("glBlendEquation(%x)\n", glParm);
1904             glBlendEquation(glParm);
1905             checkGLcall("glBlendEquation");
1906         }
1907         break;
1908
1909     case D3DRS_TEXTUREFACTOR             :
1910         {
1911             unsigned int i;
1912
1913             /* Note the texture color applies to all textures whereas 
1914                GL_TEXTURE_ENV_COLOR applies to active only */
1915             float col[4];
1916             D3DCOLORTOGLFLOAT4(Value, col);
1917             /* Set the default alpha blend color */
1918             glBlendColor(col[0], col[1], col[2], col[3]);
1919             checkGLcall("glBlendColor");
1920
1921             /* And now the default texture color as well */
1922             for (i = 0; i < GL_LIMITS(textures); i++) {
1923
1924                 /* Note the D3DRS value applies to all textures, but GL has one
1925                    per texture, so apply it now ready to be used!               */
1926                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1927                     GLACTIVETEXTURE(i);
1928                 } else if (i>0) {
1929                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1930                 }
1931
1932                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1933                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1934             }
1935         }
1936         break;
1937
1938     case D3DRS_SPECULARENABLE            : 
1939         {
1940             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
1941                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
1942                specular color. This is wrong:
1943                Separate specular color means the specular colour is maintained separately, whereas
1944                single color means it is merged in. However in both cases they are being used to
1945                some extent.
1946                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
1947                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
1948                   running 1.4 yet!
1949              */
1950               if (Value) {
1951                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1952                 checkGLcall("glMaterialfv");
1953                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1954                   glEnable(GL_COLOR_SUM_EXT);
1955                 } else {
1956                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
1957                 }
1958                 checkGLcall("glEnable(GL_COLOR_SUM)");
1959               } else {
1960                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1961
1962                 /* for the case of enabled lighting: */
1963                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1964                 checkGLcall("glMaterialfv");
1965
1966                 /* for the case of disabled lighting: */
1967                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1968                   glDisable(GL_COLOR_SUM_EXT);
1969                 } else {
1970                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
1971                 }
1972                 checkGLcall("glDisable(GL_COLOR_SUM)");
1973               }
1974         }
1975         break;
1976
1977     case D3DRS_STENCILENABLE             :
1978         if (Value) {
1979             glEnable(GL_STENCIL_TEST);
1980             checkGLcall("glEnable GL_STENCIL_TEST");
1981         } else {
1982             glDisable(GL_STENCIL_TEST);
1983             checkGLcall("glDisable GL_STENCIL_TEST");
1984         }
1985         break;
1986
1987     case D3DRS_STENCILFUNC               :
1988         {
1989            int glParm = GL_ALWAYS;
1990            int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
1991            GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
1992
1993            switch ((D3DCMPFUNC) Value) {
1994            case D3DCMP_NEVER:         glParm=GL_NEVER; break;
1995            case D3DCMP_LESS:          glParm=GL_LESS; break;
1996            case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
1997            case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
1998            case D3DCMP_GREATER:       glParm=GL_GREATER; break;
1999            case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2000            case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2001            case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2002            default:
2003                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2004            }
2005            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2006            This->stencilfunc = glParm;
2007            glStencilFunc(glParm, ref, mask);
2008            checkGLcall("glStencilFunc");
2009         }
2010         break;
2011
2012     case D3DRS_STENCILREF                :
2013         {
2014            int glParm = This->stencilfunc;
2015            int ref = 0;
2016            GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
2017
2018            ref = Value;
2019            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2020            glStencilFunc(glParm, ref, mask);
2021            checkGLcall("glStencilFunc");
2022         }
2023         break;
2024
2025     case D3DRS_STENCILMASK               :
2026         {
2027            int glParm = This->stencilfunc;
2028            int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
2029            GLuint mask = Value;
2030
2031            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2032            glStencilFunc(glParm, ref, mask);
2033            checkGLcall("glStencilFunc");
2034         }
2035         break;
2036
2037     case D3DRS_STENCILFAIL               :
2038         {
2039             GLenum fail  ; 
2040             GLenum zpass ; 
2041             GLenum zfail ; 
2042
2043             fail = StencilOp(Value);
2044             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2045             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2046             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2047             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2048
2049             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2050             glStencilOp(fail, zfail, zpass);
2051             checkGLcall("glStencilOp(fail, zfail, zpass);");
2052         }
2053         break;
2054     case D3DRS_STENCILZFAIL              :
2055         {
2056             GLenum fail  ; 
2057             GLenum zpass ; 
2058             GLenum zfail ; 
2059
2060             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2061             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2062             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2063             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2064             zfail = StencilOp(Value);
2065
2066             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2067             glStencilOp(fail, zfail, zpass);
2068             checkGLcall("glStencilOp(fail, zfail, zpass);");
2069         }
2070         break;
2071     case D3DRS_STENCILPASS               :
2072         {
2073             GLenum fail  ; 
2074             GLenum zpass ; 
2075             GLenum zfail ; 
2076
2077             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2078             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2079             zpass = StencilOp(Value);
2080             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2081             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2082
2083             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2084             glStencilOp(fail, zfail, zpass);
2085             checkGLcall("glStencilOp(fail, zfail, zpass);");
2086         }
2087         break;
2088
2089     case D3DRS_STENCILWRITEMASK          :
2090         {
2091             glStencilMask(Value);
2092             TRACE("glStencilMask(%lu)\n", Value);
2093             checkGLcall("glStencilMask");
2094         }
2095         break;
2096
2097     case D3DRS_FOGENABLE                 :
2098         {
2099           if (Value/* && This->stateBlock->renderState[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2100                glEnable(GL_FOG);
2101                checkGLcall("glEnable GL_FOG");
2102             } else {
2103                glDisable(GL_FOG);
2104                checkGLcall("glDisable GL_FOG");
2105             }
2106         }
2107         break;
2108
2109     case D3DRS_RANGEFOGENABLE            :
2110         {
2111             if (Value) {
2112               TRACE("Enabled RANGEFOG");
2113             } else {
2114               TRACE("Disabled RANGEFOG");
2115             }
2116         }
2117         break;
2118
2119     case D3DRS_FOGCOLOR                  :
2120         {
2121             float col[4];
2122             D3DCOLORTOGLFLOAT4(Value, col);
2123             /* Set the default alpha blend color */
2124             glFogfv(GL_FOG_COLOR, &col[0]);
2125             checkGLcall("glFog GL_FOG_COLOR");
2126         }
2127         break;
2128
2129     case D3DRS_FOGTABLEMODE              :
2130         { 
2131           glHint(GL_FOG_HINT, GL_NICEST);
2132           switch (Value) {
2133           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2134           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2135           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2136           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2137           default:
2138             FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2139           }
2140           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2141             glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2142           }
2143         }
2144         break;
2145
2146     case D3DRS_FOGVERTEXMODE             :
2147         { 
2148           glHint(GL_FOG_HINT, GL_FASTEST);
2149           switch (Value) {
2150           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2151           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2152           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2153           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2154           default:
2155             FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2156           }
2157           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2158             glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2159           }
2160         }
2161         break;
2162
2163     case D3DRS_FOGSTART                  :
2164         {
2165             tmpvalue.d = Value;
2166             glFogfv(GL_FOG_START, &tmpvalue.f);
2167             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2168             TRACE("Fog Start == %f\n", tmpvalue.f);
2169         }
2170         break;
2171
2172     case D3DRS_FOGEND                    :
2173         {
2174             tmpvalue.d = Value;
2175             glFogfv(GL_FOG_END, &tmpvalue.f);
2176             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2177             TRACE("Fog End == %f\n", tmpvalue.f);
2178         }
2179         break;
2180
2181     case D3DRS_FOGDENSITY                :
2182         {
2183             tmpvalue.d = Value;
2184             glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2185             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2186         }
2187         break;
2188
2189     case D3DRS_VERTEXBLEND               :
2190         {
2191           This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2192           TRACE("Vertex Blending state to %ld\n",  Value);
2193         }
2194         break;
2195
2196     case D3DRS_TWEENFACTOR               :
2197         {
2198           tmpvalue.d = Value;
2199           This->updateStateBlock->tween_factor = tmpvalue.f;
2200           TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2201         }
2202         break;
2203
2204     case D3DRS_INDEXEDVERTEXBLENDENABLE  :
2205         {
2206           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2207         }
2208         break;
2209
2210     case D3DRS_COLORVERTEX               :
2211     case D3DRS_DIFFUSEMATERIALSOURCE     :
2212     case D3DRS_SPECULARMATERIALSOURCE    :
2213     case D3DRS_AMBIENTMATERIALSOURCE     :
2214     case D3DRS_EMISSIVEMATERIALSOURCE    :
2215         {
2216             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2217
2218             if (This->stateBlock->renderState[D3DRS_COLORVERTEX]) {
2219                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2220                       This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE],
2221                       This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE],
2222                       This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE],
2223                       This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE]);
2224
2225                 if (This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2226                     if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2227                         Parm = GL_AMBIENT_AND_DIFFUSE;
2228                     } else {
2229                         Parm = GL_DIFFUSE;
2230                     }
2231                 } else if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2232                     Parm = GL_AMBIENT;
2233                 } else if (This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2234                     Parm = GL_EMISSION;
2235                 } else if (This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2236                     Parm = GL_SPECULAR;
2237                 } else {
2238                     Parm = -1;
2239                 }
2240
2241                 if (Parm == -1) {
2242                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2243                 } else {
2244                     This->tracking_color = NEEDS_TRACKING;
2245                     This->tracking_parm  = Parm;
2246                 }
2247
2248             } else {
2249                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2250             }
2251         }
2252         break; 
2253
2254     case D3DRS_LINEPATTERN               :
2255         {
2256             union {
2257                 DWORD                 d;
2258                 D3DLINEPATTERN        lp;
2259             } tmppattern;
2260             tmppattern.d = Value;
2261
2262             TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2263
2264             if (tmppattern.lp.wRepeatFactor) {
2265                 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2266                 checkGLcall("glLineStipple(repeat, linepattern)");
2267                 glEnable(GL_LINE_STIPPLE);
2268                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2269             } else {
2270                 glDisable(GL_LINE_STIPPLE);
2271                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2272             }
2273         }
2274         break;
2275
2276     case D3DRS_ZBIAS                     :
2277         {
2278             if (Value) {
2279                 tmpvalue.d = Value;
2280                 TRACE("ZBias value %f\n", tmpvalue.f);
2281                 glPolygonOffset(0, -tmpvalue.f);
2282                 checkGLcall("glPolygonOffset(0, -Value)");
2283                 glEnable(GL_POLYGON_OFFSET_FILL);
2284                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2285                 glEnable(GL_POLYGON_OFFSET_LINE);
2286                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2287                 glEnable(GL_POLYGON_OFFSET_POINT);
2288                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2289             } else {
2290                 glDisable(GL_POLYGON_OFFSET_FILL);
2291                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2292                 glDisable(GL_POLYGON_OFFSET_LINE);
2293                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2294                 glDisable(GL_POLYGON_OFFSET_POINT);
2295                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2296             }
2297         }
2298         break;
2299
2300     case D3DRS_NORMALIZENORMALS          :
2301         if (Value) {
2302             glEnable(GL_NORMALIZE);
2303             checkGLcall("glEnable(GL_NORMALIZE);");
2304         } else {
2305             glDisable(GL_NORMALIZE);
2306             checkGLcall("glDisable(GL_NORMALIZE);");
2307         }
2308         break;
2309
2310     case D3DRS_POINTSIZE                 :
2311         tmpvalue.d = Value;
2312         TRACE("Set point size to %f\n", tmpvalue.f);
2313         glPointSize(tmpvalue.f);
2314         checkGLcall("glPointSize(...);");
2315         break;
2316
2317     case D3DRS_POINTSIZE_MIN             :
2318         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2319           tmpvalue.d = Value;
2320           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2321           checkGLcall("glPointParameterfEXT(...);");
2322         } else {
2323           FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2324         }
2325         break;
2326
2327     case D3DRS_POINTSIZE_MAX             :
2328         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2329           tmpvalue.d = Value;
2330           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2331           checkGLcall("glPointParameterfEXT(...);");
2332         } else {
2333           FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2334         }
2335         break;
2336
2337     case D3DRS_POINTSCALE_A              :
2338     case D3DRS_POINTSCALE_B              :
2339     case D3DRS_POINTSCALE_C              :
2340     case D3DRS_POINTSCALEENABLE          :
2341         {
2342             /* If enabled, supply the parameters, otherwise fall back to defaults */
2343             if (This->stateBlock->renderState[D3DRS_POINTSCALEENABLE]) {
2344                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2345                 att[0] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_A]);
2346                 att[1] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_B]);
2347                 att[2] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_C]);
2348
2349                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2350                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2351                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2352                 } else {
2353                   TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2354                 }
2355             } else {
2356                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2357                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2358                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2359                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2360                 } else {
2361                   TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2362                 }
2363             }
2364             break;
2365         }
2366
2367     case D3DRS_COLORWRITEENABLE          :
2368       {
2369         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n", 
2370               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
2371               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2372               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
2373               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0); 
2374         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE, 
2375                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2376                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE, 
2377                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2378         checkGLcall("glColorMask(...)");
2379       }
2380       break;
2381
2382     case D3DRS_LOCALVIEWER               :
2383       {
2384         GLint state = (Value) ? 1 : 0;
2385         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);        
2386         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2387       }
2388       break;
2389
2390     case D3DRS_LASTPIXEL                 :
2391       {
2392         if (Value) {
2393           TRACE("Last Pixel Drawing Enabled\n");  
2394         } else {
2395           FIXME("Last Pixel Drawing Disabled, not handled yet\n");  
2396         }
2397       }
2398       break;
2399
2400     case D3DRS_SOFTWAREVERTEXPROCESSING  :
2401       {
2402         if (Value) {
2403           TRACE("Software Processing Enabled\n");  
2404         } else {
2405           TRACE("Software Processing Disabled\n");  
2406         }
2407       }
2408       break;
2409
2410       /** not supported */
2411     case D3DRS_ZVISIBLE                  :
2412       {
2413         LEAVE_GL();
2414         return D3DERR_INVALIDCALL;
2415       }
2416
2417         /* Unhandled yet...! */
2418     case D3DRS_EDGEANTIALIAS             :
2419     case D3DRS_WRAP0                     :
2420     case D3DRS_WRAP1                     :
2421     case D3DRS_WRAP2                     :
2422     case D3DRS_WRAP3                     :
2423     case D3DRS_WRAP4                     :
2424     case D3DRS_WRAP5                     :
2425     case D3DRS_WRAP6                     :
2426     case D3DRS_WRAP7                     :
2427     case D3DRS_POINTSPRITEENABLE         :
2428     case D3DRS_MULTISAMPLEANTIALIAS      :
2429     case D3DRS_MULTISAMPLEMASK           :
2430     case D3DRS_PATCHEDGESTYLE            :
2431     case D3DRS_PATCHSEGMENTS             :
2432     case D3DRS_DEBUGMONITORTOKEN         :
2433     case D3DRS_POSITIONORDER             :
2434     case D3DRS_NORMALORDER               :
2435         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2436         FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2437         break;
2438     default:
2439         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2440     }
2441
2442     LEAVE_GL();
2443
2444     return D3D_OK;
2445 }
2446
2447 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
2448     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2449     TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
2450     *pValue = This->stateBlock->renderState[State];
2451     return D3D_OK;
2452 }
2453
2454
2455 /*****
2456  * Get / Set Texture Stage States
2457  * TODO: Verify against dx9 definitions
2458  *****/
2459 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
2460     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2461     union {
2462         float f;
2463         DWORD d;
2464     } tmpvalue;
2465
2466     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
2467    
2468     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
2469
2470     /* Reject invalid texture units */
2471     if (Stage >= GL_LIMITS(textures)) {
2472         TRACE("Attempt to access invalid texture rejected\n");
2473         return D3DERR_INVALIDCALL;
2474     }
2475
2476     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
2477     This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
2478     This->updateStateBlock->textureState[Stage][Type] = Value;
2479
2480     /* Handle recording of state blocks */
2481     if (This->isRecordingState) {
2482         TRACE("Recording... not performing anything\n");
2483         return D3D_OK;
2484     }
2485
2486     ENTER_GL();
2487
2488     /* Make appropriate texture active */
2489     VTRACE(("Activating appropriate texture state %ld\n", Stage));
2490     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2491         GLACTIVETEXTURE(Stage);
2492     } else if (Stage > 0) {
2493         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2494     }
2495
2496     switch (Type) {
2497
2498     case D3DTSS_MINFILTER             :
2499     case D3DTSS_MIPFILTER             :
2500         {
2501             DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
2502             DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
2503             GLint realVal = GL_LINEAR;
2504
2505             if (ValueMIN == D3DTEXF_NONE) {
2506               /* Doesn't really make sense - Windows just seems to disable
2507                  mipmapping when this occurs                              */
2508               FIXME("Odd - minfilter of none, just disabling mipmaps\n");
2509               realVal = GL_LINEAR;
2510             } else if (ValueMIN == D3DTEXF_POINT) {
2511                 /* GL_NEAREST_* */
2512               if (ValueMIP == D3DTEXF_NONE) {
2513                     realVal = GL_NEAREST;
2514                 } else if (ValueMIP == D3DTEXF_POINT) {
2515                     realVal = GL_NEAREST_MIPMAP_NEAREST;
2516                 } else if (ValueMIP == D3DTEXF_LINEAR) {
2517                     realVal = GL_NEAREST_MIPMAP_LINEAR;
2518                 } else {
2519                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2520                     realVal = GL_NEAREST;
2521                 }
2522             } else if (ValueMIN == D3DTEXF_LINEAR) {
2523                 /* GL_LINEAR_* */
2524                 if (ValueMIP == D3DTEXF_NONE) {
2525                     realVal = GL_LINEAR;
2526                 } else if (ValueMIP == D3DTEXF_POINT) {
2527                     realVal = GL_LINEAR_MIPMAP_NEAREST;
2528                 } else if (ValueMIP == D3DTEXF_LINEAR) {
2529                     realVal = GL_LINEAR_MIPMAP_LINEAR;
2530                 } else {
2531                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2532                     realVal = GL_LINEAR;
2533                 }
2534             } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
2535               if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2536                 if (ValueMIP == D3DTEXF_NONE) {
2537                   realVal = GL_LINEAR_MIPMAP_LINEAR;                  
2538                 } else if (ValueMIP == D3DTEXF_POINT) {
2539                   realVal = GL_LINEAR_MIPMAP_NEAREST;
2540                 } else if (ValueMIP == D3DTEXF_LINEAR) {
2541                     realVal = GL_LINEAR_MIPMAP_LINEAR;
2542                 } else {
2543                   FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2544                   realVal = GL_LINEAR;
2545                 }
2546               } else {
2547                 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
2548                 realVal = GL_LINEAR;
2549               }
2550             } else {
2551                 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
2552                 realVal = GL_LINEAR_MIPMAP_LINEAR;
2553             }
2554
2555             TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
2556             glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
2557             checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
2558             /**
2559              * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
2560              */
2561             if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
2562               glTexParameteri(This->stateBlock->textureDimensions[Stage], 
2563                               GL_TEXTURE_MAX_ANISOTROPY_EXT, 
2564                               This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2565               checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
2566             }
2567         }
2568         break;
2569
2570     case D3DTSS_MAGFILTER             :
2571       {
2572         DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
2573         GLint realVal = GL_NEAREST;
2574
2575         if (ValueMAG == D3DTEXF_POINT) {
2576           realVal = GL_NEAREST;
2577         } else if (ValueMAG == D3DTEXF_LINEAR) {
2578           realVal = GL_LINEAR;
2579         } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
2580           if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2581             realVal = GL_LINEAR;
2582           } else {
2583             FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
2584             realVal = GL_NEAREST;
2585           }
2586         } else {
2587           FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
2588           realVal = GL_NEAREST;
2589         }
2590         TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
2591         glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
2592         checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
2593         /**
2594          * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
2595          */
2596         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
2597           glTexParameteri(This->stateBlock->textureDimensions[Stage], 
2598                           GL_TEXTURE_MAX_ANISOTROPY_EXT, 
2599                           This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2600           checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
2601         }
2602       }
2603       break;
2604
2605     case D3DTSS_MAXMIPLEVEL           :
2606       {
2607         /**
2608          * Not really the same, but the more apprioprate than nothing
2609          */
2610         glTexParameteri(This->stateBlock->textureDimensions[Stage], 
2611                         GL_TEXTURE_BASE_LEVEL, 
2612                         This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
2613         checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
2614       }
2615       break;
2616
2617     case D3DTSS_MAXANISOTROPY         :
2618       {        
2619         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2620           glTexParameteri(This->stateBlock->textureDimensions[Stage], 
2621                           GL_TEXTURE_MAX_ANISOTROPY_EXT, 
2622                           This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2623           checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
2624         }
2625       }
2626       break;
2627
2628     case D3DTSS_MIPMAPLODBIAS         :
2629       {        
2630         if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2631           tmpvalue.d = Value;
2632           glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, 
2633                     GL_TEXTURE_LOD_BIAS_EXT,
2634                     tmpvalue.f);
2635           checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2636         }
2637       }
2638       break;
2639
2640     case D3DTSS_ALPHAOP               :
2641     case D3DTSS_COLOROP               :
2642         {
2643
2644             if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
2645                 /* TODO: Disable by making this and all later levels disabled */
2646                 glDisable(GL_TEXTURE_1D);
2647                 checkGLcall("Disable GL_TEXTURE_1D");
2648                 glDisable(GL_TEXTURE_2D);
2649                 checkGLcall("Disable GL_TEXTURE_2D");
2650                 glDisable(GL_TEXTURE_3D);
2651                 checkGLcall("Disable GL_TEXTURE_3D");
2652                 break; /* Don't bother setting the texture operations */
2653             } else {
2654                 /* Enable only the appropriate texture dimension */
2655                 if (Type == D3DTSS_COLOROP) {
2656                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2657                         glEnable(GL_TEXTURE_1D);
2658                         checkGLcall("Enable GL_TEXTURE_1D");
2659                     } else {
2660                         glDisable(GL_TEXTURE_1D);
2661                         checkGLcall("Disable GL_TEXTURE_1D");
2662                     } 
2663                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
2664                       if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
2665                         glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
2666                         checkGLcall("Enable GL_TEXTURE_2D");
2667                       } else {
2668                         glEnable(GL_TEXTURE_2D);
2669                         checkGLcall("Enable GL_TEXTURE_2D");
2670                       }
2671                     } else {
2672                         glDisable(GL_TEXTURE_2D);
2673                         checkGLcall("Disable GL_TEXTURE_2D");
2674                     }
2675                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
2676                         glEnable(GL_TEXTURE_3D);
2677                         checkGLcall("Enable GL_TEXTURE_3D");
2678                     } else {
2679                         glDisable(GL_TEXTURE_3D);
2680                         checkGLcall("Disable GL_TEXTURE_3D");
2681                     }
2682                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
2683                         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
2684                         checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
2685                     } else {
2686                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2687                         checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
2688                     }
2689                 }
2690             }
2691             /* Drop through... (Except disable case) */
2692         case D3DTSS_COLORARG0             :
2693         case D3DTSS_COLORARG1             :
2694         case D3DTSS_COLORARG2             :
2695         case D3DTSS_ALPHAARG0             :
2696         case D3DTSS_ALPHAARG1             :
2697         case D3DTSS_ALPHAARG2             :
2698             {
2699                 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 || 
2700                                    Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
2701                 if (isAlphaArg) {
2702                     set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
2703                                This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1], 
2704                                This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2], 
2705                                This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
2706                 } else {
2707                     set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
2708                                This->stateBlock->textureState[Stage][D3DTSS_COLORARG1], 
2709                                This->stateBlock->textureState[Stage][D3DTSS_COLORARG2], 
2710                                This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
2711                 }
2712             }
2713             break;
2714         }
2715
2716     case D3DTSS_ADDRESSU              :
2717     case D3DTSS_ADDRESSV              :
2718     case D3DTSS_ADDRESSW              :
2719         {
2720             GLint wrapParm = GL_REPEAT;
2721
2722             switch (Value) {
2723             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
2724             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;      
2725             case D3DTADDRESS_BORDER: 
2726               {
2727                 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2728                   wrapParm = GL_CLAMP_TO_BORDER_ARB; 
2729                 } else {
2730                   /* FIXME: Not right, but better */
2731                   FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
2732                   wrapParm = GL_REPEAT; 
2733                 }
2734               }
2735               break;
2736             case D3DTADDRESS_MIRROR: 
2737               {
2738                 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2739                   wrapParm = GL_MIRRORED_REPEAT_ARB;
2740                 } else {
2741                   /* Unsupported in OpenGL pre-1.4 */
2742                   FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
2743                   wrapParm = GL_REPEAT;
2744                 }
2745               }
2746               break;
2747             case D3DTADDRESS_MIRRORONCE: 
2748               {
2749                 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2750                   wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
2751                 } else {
2752                   FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
2753                   wrapParm = GL_REPEAT; 
2754                 }
2755               }
2756               break;
2757
2758             default:
2759                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
2760                 wrapParm = GL_REPEAT; 
2761             }
2762
2763             switch (Type) {
2764             case D3DTSS_ADDRESSU:
2765                 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2766                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
2767                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
2768                 break;
2769             case D3DTSS_ADDRESSV:
2770                 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2771                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
2772                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
2773                 break;
2774             case D3DTSS_ADDRESSW:
2775                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2776                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
2777                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
2778                 break;
2779             default: /* nop */
2780                       break; /** stupic compilator */
2781             }
2782         }
2783         break;
2784
2785     case D3DTSS_BORDERCOLOR           :
2786         {
2787             float col[4];
2788             D3DCOLORTOGLFLOAT4(Value, col);
2789             TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value); 
2790             glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
2791             checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
2792         }
2793         break;
2794
2795     case D3DTSS_TEXCOORDINDEX         :
2796         {
2797             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
2798
2799             /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include 
2800                   one flag, you can still specify an index value, which the system uses to 
2801                   determine the texture wrapping mode.  
2802                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2803                   means use the vertex position (camera-space) as the input texture coordinates 
2804                   for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render 
2805                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
2806                   to the TEXCOORDINDEX value */
2807           
2808             /** 
2809              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos 
2810              */
2811             switch (Value & 0xFFFF0000) {
2812             case D3DTSS_TCI_PASSTHRU:
2813               /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2814               glDisable(GL_TEXTURE_GEN_S);
2815               glDisable(GL_TEXTURE_GEN_T);
2816               glDisable(GL_TEXTURE_GEN_R);
2817               checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
2818               break;
2819
2820             case D3DTSS_TCI_CAMERASPACEPOSITION:
2821               /* CameraSpacePosition means use the vertex position, transformed to camera space, 
2822                  as the input texture coordinates for this stage's texture transformation. This 
2823                  equates roughly to EYE_LINEAR                                                  */
2824               {
2825                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2826                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2827                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2828                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2829                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2830
2831                 glMatrixMode(GL_MODELVIEW);
2832                 glPushMatrix();
2833                 glLoadIdentity();
2834                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2835                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2836                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2837                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2838                 glPopMatrix();
2839                 
2840                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2841                 glEnable(GL_TEXTURE_GEN_S);
2842                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2843                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2844                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2845                 glEnable(GL_TEXTURE_GEN_T);
2846                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2847                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2848                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2849                 glEnable(GL_TEXTURE_GEN_R);
2850                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2851                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2852                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2853               }
2854               break;
2855
2856             case D3DTSS_TCI_CAMERASPACENORMAL:
2857               {
2858                 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2859                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2860                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2861                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2862                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2863                   TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2864
2865                   glMatrixMode(GL_MODELVIEW);
2866                   glPushMatrix();
2867                   glLoadIdentity();
2868                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2869                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2870                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2871                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2872                   glPopMatrix();
2873                   
2874                   glEnable(GL_TEXTURE_GEN_S);
2875                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2876                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2877                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2878                   glEnable(GL_TEXTURE_GEN_T);
2879                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2880                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2881                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2882                   glEnable(GL_TEXTURE_GEN_R);
2883                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2884                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2885                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2886                 }
2887               }
2888               break;
2889
2890             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2891               {
2892                 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2893                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2894                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2895                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2896                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2897                   TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2898                   
2899                   glMatrixMode(GL_MODELVIEW);
2900                   glPushMatrix();
2901                   glLoadIdentity();
2902                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2903                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2904                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2905                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2906                   glPopMatrix();
2907                   
2908                   glEnable(GL_TEXTURE_GEN_S);
2909                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2910                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2911                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2912                   glEnable(GL_TEXTURE_GEN_T);
2913                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2914                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2915                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2916                   glEnable(GL_TEXTURE_GEN_R);
2917                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2918                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2919                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2920                 }
2921               }
2922               break;
2923
2924             /* Unhandled types: */
2925             default:
2926                 /* Todo: */
2927                 /* ? disable GL_TEXTURE_GEN_n ? */ 
2928                 glDisable(GL_TEXTURE_GEN_S);
2929                 glDisable(GL_TEXTURE_GEN_T);
2930                 glDisable(GL_TEXTURE_GEN_R);
2931                 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
2932                 break;
2933             }
2934         }
2935         break;
2936
2937         /* Unhandled */
2938     case D3DTSS_TEXTURETRANSFORMFLAGS :
2939         set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
2940         break; 
2941
2942     case D3DTSS_BUMPENVMAT00          :
2943     case D3DTSS_BUMPENVMAT01          :
2944         TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
2945         break;
2946     case D3DTSS_BUMPENVMAT10          :
2947     case D3DTSS_BUMPENVMAT11          :
2948         TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
2949         break;
2950
2951     case D3DTSS_BUMPENVLSCALE         :
2952       TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2953       break;
2954
2955     case D3DTSS_BUMPENVLOFFSET        :
2956       TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2957       break;
2958
2959     case D3DTSS_RESULTARG             :
2960       TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2961       break;
2962
2963     default:
2964         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
2965         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2966     }
2967
2968     LEAVE_GL();
2969
2970     return D3D_OK;
2971 }
2972
2973 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
2974     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2975     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
2976     *pValue = This->updateStateBlock->textureState[Stage][Type];
2977     return D3D_OK;
2978 }
2979
2980 /*****
2981  * Scene related functions
2982  *****/
2983 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
2984     /* At the moment we have no need for any functionality at the beginning
2985        of a scene                                                          */
2986     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2987     TRACE("(%p) : stub\n", This);
2988     return D3D_OK;
2989 }
2990
2991 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
2992     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2993     TRACE("(%p)\n", This);
2994
2995     ENTER_GL();
2996
2997     glFlush();
2998     checkGLcall("glFlush");
2999
3000     if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
3001
3002         /* If we are rendering to a texture (surface) then flag it as dirty.
3003            A surfaces container is either the appropriate texture or the device itself
3004               depending on how the surface was created.                                */
3005         if (This->renderTarget != NULL && ((IWineD3DDeviceImpl *)This->renderTarget->container != This)) {
3006
3007             IWineD3DBaseTexture *cont = (IWineD3DBaseTexture *)This->renderTarget->container;
3008             /** always dirtify for now. we must find a better way to see that surface have been modified */
3009             This->renderTarget->inPBuffer = TRUE;
3010             This->renderTarget->inTexture = FALSE;
3011             IWineD3DBaseTexture_SetDirty(cont, TRUE);
3012             IWineD3DBaseTexture_PreLoad(cont);
3013             This->renderTarget->inPBuffer = FALSE;
3014         }
3015     }
3016
3017     LEAVE_GL();
3018     return D3D_OK;
3019 }
3020
3021 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface, 
3022                                           CONST RECT* pSourceRect, CONST RECT* pDestRect, 
3023                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
3024     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3025     TRACE("(%p) Presenting the frame\n", This);
3026
3027     ENTER_GL();
3028
3029     if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
3030
3031     glXSwapBuffers(This->display, This->drawable);
3032     /* Don't call checkGLcall, as glGetError is not applicable here */
3033     
3034     TRACE("glXSwapBuffers called, Starting new frame\n");
3035
3036     /* FPS support */
3037     if (TRACE_ON(d3d_fps))
3038     {
3039         static long prev_time, frames;
3040
3041         DWORD time = GetTickCount();
3042         frames++;
3043         /* every 1.5 seconds */
3044         if (time - prev_time > 1500) {
3045             TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
3046             prev_time = time;
3047             frames = 0;
3048         }
3049     }
3050
3051 #if defined(FRAME_DEBUGGING)
3052 {
3053     if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
3054         if (!isOn) {
3055             isOn = TRUE;
3056             FIXME("Enabling D3D Trace\n");
3057             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
3058 #if defined(SHOW_FRAME_MAKEUP)
3059             FIXME("Singe Frame snapshots Starting\n");
3060             isDumpingFrames = TRUE;
3061             glClear(GL_COLOR_BUFFER_BIT);
3062 #endif
3063
3064 #if defined(SINGLE_FRAME_DEBUGGING)
3065         } else {
3066 #if defined(SHOW_FRAME_MAKEUP)
3067             FIXME("Singe Frame snapshots Finishing\n");
3068             isDumpingFrames = FALSE;
3069 #endif
3070             FIXME("Singe Frame trace complete\n");
3071             DeleteFileA("C:\\D3DTRACE");
3072             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3073 #endif
3074         }
3075     } else {
3076         if (isOn) {
3077             isOn = FALSE;
3078 #if defined(SHOW_FRAME_MAKEUP)
3079             FIXME("Singe Frame snapshots Finishing\n");
3080             isDumpingFrames = FALSE;
3081 #endif
3082             FIXME("Disabling D3D Trace\n");
3083             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3084         }
3085     }
3086 }
3087 #endif
3088
3089     LEAVE_GL();
3090     /* Although this is not strictly required, a simple demo showed this does occur
3091        on (at least non-debug) d3d                                                  */
3092     if (This->presentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
3093        IWineD3DDevice_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
3094     }
3095
3096     return D3D_OK;
3097 }
3098
3099 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects, 
3100                                         DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
3101     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3102
3103     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
3104       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
3105       when the depth-buffer format does not contain stencil buffer information, this method fails. */
3106     GLbitfield     glMask = 0;
3107     GLboolean      old_ztest;
3108     GLfloat        old_z_clear_value;
3109     GLint          old_stencil_clear_value;
3110     GLfloat        old_color_clear_value[4];
3111     unsigned int   i;
3112     CONST D3DRECT* curRect;
3113
3114     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
3115           Count, pRects, Flags, Z, Stencil);
3116
3117     ENTER_GL();
3118
3119     glEnable(GL_SCISSOR_TEST);
3120     checkGLcall("glEnable GL_SCISSOR_TEST");
3121
3122     if (Count > 0 && pRects) {
3123         curRect = pRects;
3124     } else {
3125         curRect = NULL;
3126     }
3127
3128     /* Only set the values up once, as they are not changing */
3129     if (Flags & D3DCLEAR_STENCIL) {        
3130         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
3131         glClearStencil(Stencil);
3132         checkGLcall("glClearStencil");
3133         glMask = glMask | GL_STENCIL_BUFFER_BIT;
3134         glStencilMask(0xFFFFFFFF);
3135     }
3136
3137     if (Flags & D3DCLEAR_ZBUFFER) {
3138         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
3139         glDepthMask(GL_TRUE); 
3140         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
3141         glClearDepth(Z);
3142         checkGLcall("glClearDepth");
3143         glMask = glMask | GL_DEPTH_BUFFER_BIT;
3144     }
3145
3146     if (Flags & D3DCLEAR_TARGET) {
3147         TRACE("Clearing screen with glClear to color %lx\n", Color);
3148         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
3149         glClearColor(((Color >> 16) & 0xFF) / 255.0f, 
3150                      ((Color >>  8) & 0xFF) / 255.0f,
3151                      ((Color >>  0) & 0xFF) / 255.0f, 
3152                      ((Color >> 24) & 0xFF) / 255.0f);
3153         checkGLcall("glClearColor");
3154
3155         /* Clear ALL colors! */
3156         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3157         glMask = glMask | GL_COLOR_BUFFER_BIT;
3158     }
3159
3160     /* Now process each rect in turn */
3161     for (i = 0; i < Count || i == 0; i++) {
3162
3163         if (curRect) {
3164             /* Note gl uses lower left, width/height */
3165             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
3166                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
3167                   curRect->x1, (This->renderTarget->currentDesc.Height - curRect->y2), 
3168                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3169             glScissor(curRect->x1, (This->renderTarget->currentDesc.Height - curRect->y2), 
3170                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3171             checkGLcall("glScissor");
3172         } else {
3173             glScissor(This->stateBlock->viewport.X, 
3174                       (This->renderTarget->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)), 
3175                       This->stateBlock->viewport.Width, 
3176                       This->stateBlock->viewport.Height);
3177             checkGLcall("glScissor");
3178         }
3179
3180         /* Clear the selected rectangle (or full screen) */
3181         glClear(glMask);
3182         checkGLcall("glClear");
3183
3184         /* Step to the next rectangle */
3185         if (curRect) curRect = curRect + sizeof(D3DRECT);
3186     }
3187
3188     /* Restore the old values (why..?) */
3189     if (Flags & D3DCLEAR_STENCIL) {
3190         glClearStencil(old_stencil_clear_value);
3191         glStencilMask(This->stateBlock->renderState[D3DRS_STENCILWRITEMASK]);
3192     }    
3193     if (Flags & D3DCLEAR_ZBUFFER) {
3194         glDepthMask(old_ztest);
3195         glClearDepth(old_z_clear_value);
3196     }
3197     if (Flags & D3DCLEAR_TARGET) {
3198         glClearColor(old_color_clear_value[0], 
3199                      old_color_clear_value[1],
3200                      old_color_clear_value[2], 
3201                      old_color_clear_value[3]);
3202         glColorMask(This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE, 
3203                     This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3204                     This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE, 
3205                     This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3206     }
3207
3208     glDisable(GL_SCISSOR_TEST);
3209     checkGLcall("glDisable");
3210     LEAVE_GL();
3211
3212     return D3D_OK;
3213 }
3214
3215 /*****
3216  * Drawing functions
3217  *****/
3218 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, 
3219                                                 UINT PrimitiveCount) {
3220
3221     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3222     This->stateBlock->streamIsUP = FALSE;
3223
3224     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, 
3225                                debug_d3dprimitivetype(PrimitiveType), 
3226                                StartVertex, PrimitiveCount);
3227     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3228
3229     return D3D_OK;
3230 }
3231
3232 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
3233 HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface, 
3234                                                            D3DPRIMITIVETYPE PrimitiveType,
3235                                                            INT baseVIndex, UINT minIndex,
3236                                                            UINT NumVertices,UINT startIndex,UINT primCount) {
3237
3238     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
3239     UINT                 idxStride = 2;
3240     IWineD3DIndexBuffer *pIB;
3241     D3DINDEXBUFFER_DESC  IdxBufDsc;
3242     
3243     pIB = This->stateBlock->pIndexData;
3244     This->stateBlock->streamIsUP = FALSE;
3245
3246     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This, 
3247           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3248           minIndex, NumVertices, startIndex, baseVIndex, primCount);
3249
3250     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
3251     if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3252         idxStride = 2;
3253     } else {
3254         idxStride = 4;
3255     }
3256
3257     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, 
3258                       startIndex, idxStride, 
3259                       ((IWineD3DIndexBufferImpl *) pIB)->allocatedMemory,
3260                       minIndex);
3261
3262     return D3D_OK;
3263 }
3264
3265 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3266                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
3267                                                     UINT VertexStreamZeroStride) {
3268     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3269
3270     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, 
3271              debug_d3dprimitivetype(PrimitiveType), 
3272              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3273
3274     if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
3275
3276     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
3277     This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData; 
3278     This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
3279     This->stateBlock->streamIsUP = TRUE;
3280     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3281     This->stateBlock->stream_stride[0] = 0;
3282     This->stateBlock->stream_source[0] = NULL;
3283
3284     /*stream zero settings set to null at end, as per the msdn */
3285     return D3D_OK;
3286 }
3287
3288 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3289                                                              UINT MinVertexIndex,
3290                                                              UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3291                                                              D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3292                                                              UINT VertexStreamZeroStride) {
3293     int                 idxStride;
3294     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3295
3296     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", 
3297              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3298              MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,  
3299              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3300
3301     if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
3302
3303     if (IndexDataFormat == D3DFMT_INDEX16) {
3304         idxStride = 2;
3305     } else {
3306         idxStride = 4;
3307     }
3308
3309     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
3310     This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
3311     This->stateBlock->streamIsUP = TRUE;
3312     This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
3313
3314     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
3315
3316     /* stream zero settings set to null at end as per the msdn */
3317     This->stateBlock->stream_source[0] = NULL;
3318     This->stateBlock->stream_stride[0] = 0;
3319     IWineD3DDevice_SetIndices(iface, NULL, 0);
3320
3321     return D3D_OK;
3322 }
3323
3324 /**********************************************************
3325  * IUnknown parts follows
3326  **********************************************************/
3327
3328 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
3329 {
3330     return E_NOINTERFACE;
3331 }
3332
3333 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
3334     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3335     ULONG refCount = InterlockedIncrement(&This->ref);
3336
3337     TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
3338     return refCount;
3339 }
3340
3341 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
3342     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3343     ULONG refCount = InterlockedDecrement(&This->ref);
3344
3345     TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
3346
3347     if (!refCount) {
3348         IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
3349         IWineD3D_Release(This->wineD3D);
3350         HeapFree(GetProcessHeap(), 0, This);
3351     }
3352     return refCount;
3353 }
3354
3355 /**********************************************************
3356  * IWineD3DDevice VTbl follows
3357  **********************************************************/
3358
3359 IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
3360 {
3361     IWineD3DDeviceImpl_QueryInterface,
3362     IWineD3DDeviceImpl_AddRef,
3363     IWineD3DDeviceImpl_Release,
3364     IWineD3DDeviceImpl_GetParent,
3365     IWineD3DDeviceImpl_CreateVertexBuffer,
3366     IWineD3DDeviceImpl_CreateIndexBuffer,
3367     IWineD3DDeviceImpl_CreateStateBlock,
3368     IWineD3DDeviceImpl_CreateRenderTarget,
3369     IWineD3DDeviceImpl_CreateOffscreenPlainSurface,
3370     IWineD3DDeviceImpl_CreateTexture,
3371     IWineD3DDeviceImpl_CreateVolumeTexture,
3372     IWineD3DDeviceImpl_CreateVolume,
3373     IWineD3DDeviceImpl_CreateCubeTexture,
3374
3375     IWineD3DDeviceImpl_SetFVF,
3376     IWineD3DDeviceImpl_GetFVF,
3377     IWineD3DDeviceImpl_SetStreamSource,
3378     IWineD3DDeviceImpl_GetStreamSource,
3379     IWineD3DDeviceImpl_SetTransform,
3380     IWineD3DDeviceImpl_GetTransform,
3381     IWineD3DDeviceImpl_MultiplyTransform,
3382     IWineD3DDeviceImpl_SetLight,
3383     IWineD3DDeviceImpl_GetLight,
3384     IWineD3DDeviceImpl_SetLightEnable,
3385     IWineD3DDeviceImpl_GetLightEnable,
3386     IWineD3DDeviceImpl_SetClipPlane,
3387     IWineD3DDeviceImpl_GetClipPlane,
3388     IWineD3DDeviceImpl_SetClipStatus,
3389     IWineD3DDeviceImpl_GetClipStatus,
3390     IWineD3DDeviceImpl_SetMaterial,
3391     IWineD3DDeviceImpl_GetMaterial,
3392     IWineD3DDeviceImpl_SetIndices,
3393     IWineD3DDeviceImpl_GetIndices,
3394     IWineD3DDeviceImpl_SetViewport,
3395     IWineD3DDeviceImpl_GetViewport,
3396     IWineD3DDeviceImpl_SetRenderState,
3397     IWineD3DDeviceImpl_GetRenderState,
3398     IWineD3DDeviceImpl_SetTextureStageState,
3399     IWineD3DDeviceImpl_GetTextureStageState,
3400
3401     IWineD3DDeviceImpl_BeginScene,
3402     IWineD3DDeviceImpl_EndScene,
3403     IWineD3DDeviceImpl_Present,
3404     IWineD3DDeviceImpl_Clear,
3405
3406     IWineD3DDeviceImpl_DrawPrimitive,
3407     IWineD3DDeviceImpl_DrawIndexedPrimitive,
3408     IWineD3DDeviceImpl_DrawPrimitiveUP,
3409     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
3410
3411     IWineD3DDeviceImpl_SetupTextureStates
3412 };