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