Make sure the viewport is from the GL (bottom left) not the DirectX
[wine] / dlls / d3d8 / device.c
1 /*
2  * IDirect3DDevice8 implementation
3  *
4  * Copyright 2002 Jason Edmeades
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <math.h>
24
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "wingdi.h"
31 #include "wine/debug.h"
32
33 /** define  GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
34 /*#define GL_GLEXT_PROTOTYPES*/
35 #include "d3d8_private.h"
36
37 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
38 #undef GL_VERSION_1_4
39
40 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
41
42 /* Some #defines for additional diagnostics */
43
44 /* Per-vertex trace: */
45 #if 0
46 # define VTRACE(A) TRACE A
47 #else 
48 # define VTRACE(A) 
49 #endif
50
51
52 static IDirect3DVertexShaderImpl* VertexShaders[64];
53 static IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
54 static IDirect3DPixelShaderImpl*  PixelShaders[64];
55
56 /* CreateVertexShader can return > 0xFFFF */
57 #define VS_HIGHESTFIXEDFXF 0xF0000000
58
59 /*
60  * Utility functions or macros
61  */
62 #define conv_mat(mat,gl_mat)                                                                \
63 do {                                                                                        \
64     TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
65     TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
66     TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
67     TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
68     memcpy(gl_mat, (mat), 16 * sizeof(float));                                              \
69 } while (0)
70
71 #define VERTEX_SHADER(Handle) \
72   ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) ? NULL : VertexShaders[Handle]) : VertexShaders[Handle - VS_HIGHESTFIXEDFXF])
73 #define VERTEX_SHADER_DECL(Handle) \
74   ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaderDeclarations) / sizeof(IDirect3DVertexShaderDeclarationImpl*)) ? NULL : VertexShaderDeclarations[Handle]) : VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF])
75 #define PIXEL_SHADER(Handle) \
76   ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) ? NULL : PixelShaders[Handle]) : PixelShaders[Handle - VS_HIGHESTFIXEDFXF])
77
78 #define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
79
80
81
82 /* Routine common to the draw primitive and draw indexed primitive routines */
83 void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface,
84                     int PrimitiveType,
85                     long NumPrimitives,
86                     BOOL  isIndexed,
87
88                     /* For Both:*/
89                     D3DFORMAT fvf,
90                     const void *vertexBufData,
91
92                     /* for Indexed: */
93                     long  StartVertexIndex,
94                     long  StartIdx,
95                     short idxBytes,
96                     const void *idxData,
97                     int   minIndex) {
98
99     int NumVertexes = NumPrimitives;
100     IDirect3DVertexShaderImpl* vertex_shader = NULL;
101     BOOL useVertexShaderFunction = FALSE;
102
103     ICOM_THIS(IDirect3DDevice8Impl,iface);
104
105     /* Dont understand how to handle multiple streams, but if a fixed
106        FVF is passed in rather than a handle, it must use stream 0 */
107     
108     if (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF) {
109       vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
110       if (NULL == vertex_shader) {
111           ERR("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
112           return ;
113       }
114       if (NULL == vertex_shader->function) {
115           TRACE("vertex shader declared without program, using FVF pure mode\n");
116       } else {
117           useVertexShaderFunction = TRUE;
118       }
119       fvf = (D3DFORMAT) This->UpdateStateBlock->vertexShaderDecl->fvf;
120       TRACE("vertex shader declared FVF: %lx\n", This->UpdateStateBlock->vertexShaderDecl->fvf);
121       memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
122
123       /** init Constants */
124       if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
125         TRACE("vertex shader init Constant\n");
126         IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
127       }
128
129     }
130
131     {
132         int                         skip = This->StateBlock->stream_stride[0];
133         GLenum                      primType = GL_POINTS;
134         BOOL                        normal;
135         BOOL                        isRHW;
136         BOOL                        isPtSize;
137         BOOL                        isDiffuse;
138         BOOL                        isSpecular;
139         int                         numBlends;
140         BOOL                        isLastUByte4;
141         int                         numTextures;
142         int                         textureNo;
143         const char                 *curVtx = NULL;
144         const short                *pIdxBufS = NULL;
145         const long                 *pIdxBufL = NULL;
146         const char                 *curPos;
147         BOOL                        isLightingOn = FALSE;
148         int                         vx_index;
149         int                         coordIdxInfo = 0x00;    /* Information on number of coords supplied */
150         float                       s[8], t[8], r[8], q[8]; /* Holding place for tex coords             */
151         const char                 *coordPtr[8];            /* Holding place for the ptr to tex coords  */
152         int                         numCoords[8];           /* Holding place for D3DFVF_TEXTUREFORMATx  */
153
154
155         float x = 0.0f, 
156               y = 0.0f, 
157               z = 0.0f;                     /* x,y,z coordinates          */
158         float nx = 0.0f, 
159               ny =0.0, 
160               nz = 0.0f;                    /* normal x,y,z coordinates   */
161         float rhw = 0.0f;                   /* rhw                        */
162         float ptSize = 0.0f;                /* Point size                 */
163         DWORD diffuseColor = 0xFFFFFFFF;    /* Diffuse Color              */
164         DWORD specularColor = 0;            /* Specular Color             */
165
166         ENTER_GL();
167
168         if (isIndexed) {
169             if (idxBytes == 2) pIdxBufS = (short *) idxData;
170             else pIdxBufL = (long *) idxData;
171         }
172
173         /* Check vertex formats expected ? */
174         /** 
175          * FVF parser as seen it
176          * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/Reference/CPP/D3D/FlexibleVertexFormatFlags.asp 
177          */
178         normal        = fvf & D3DFVF_NORMAL;
179         isRHW         = fvf & D3DFVF_XYZRHW;
180         isLastUByte4  = fvf & D3DFVF_LASTBETA_UBYTE4;
181         numBlends     = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == isLastUByte4) ? 0 : -1); /* WARNING can be < 0 because -2 */    
182         isPtSize      = fvf & D3DFVF_PSIZE;
183         isDiffuse     = fvf & D3DFVF_DIFFUSE;
184         isSpecular    = fvf & D3DFVF_SPECULAR;
185         numTextures   = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
186         coordIdxInfo  = (fvf & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
187
188         TRACE("Drawing with FVF = %x, (n?%d, rhw?%d, ptSize(%d), diffuse?%d, specular?%d, numTextures=%d, numBlends=%d, coordIdxInfo=%x)\n",
189               fvf, normal, isRHW, isPtSize, isDiffuse, isSpecular, numTextures, numBlends, coordIdxInfo);
190
191         /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is 
192            set by the appropriate render state */
193         if (!normal) {
194             isLightingOn = glIsEnabled(GL_LIGHTING);
195             glDisable(GL_LIGHTING);
196             TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
197         }
198
199         if (isRHW) {
200             double height, width, minZ, maxZ;
201             /*
202              * Already transformed vertex do not need transform
203              * matrices. Reset all matrices to identity.
204              * Leave the default matrix in world mode.
205              */
206             glMatrixMode(GL_PROJECTION);
207             checkGLcall("glMatrixMode");
208             glLoadIdentity();
209             checkGLcall("glLoadIdentity");
210             glMatrixMode(GL_MODELVIEW);
211             checkGLcall("glMatrixMode");
212             glLoadIdentity();
213             checkGLcall("glLoadIdentity");
214             height = This->StateBlock->viewport.Height;
215             width = This->StateBlock->viewport.Width;
216             minZ = This->StateBlock->viewport.MinZ;
217             maxZ = This->StateBlock->viewport.MaxZ;
218             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
219             glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
220             checkGLcall("glOrtho");
221         } else {
222             glMatrixMode(GL_PROJECTION);
223             checkGLcall("glMatrixMode");
224             glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
225             checkGLcall("glLoadMatrixf");
226             glMatrixMode(GL_MODELVIEW);
227             checkGLcall("glMatrixMode");
228             glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
229             checkGLcall("glLoadMatrixf");
230             glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
231             checkGLcall("glMultMatrixf");
232         }
233
234         /* Set OpenGL to the appropriate Primitive Type */
235         switch (PrimitiveType) {
236         case D3DPT_POINTLIST:
237             TRACE("POINTS\n");
238             primType = GL_POINTS;
239             NumVertexes = NumPrimitives;
240             break;
241
242         case D3DPT_LINELIST:
243             TRACE("LINES\n");
244             primType = GL_LINES;
245             NumVertexes = NumPrimitives * 2;
246             break;
247
248         case D3DPT_LINESTRIP:
249             TRACE("LINE_STRIP\n");
250             primType = GL_LINE_STRIP;
251             NumVertexes = NumPrimitives + 1;
252             break;
253
254         case D3DPT_TRIANGLELIST:
255             TRACE("TRIANGLES\n");
256             primType = GL_TRIANGLES;
257             NumVertexes = NumPrimitives * 3;
258             break;
259
260         case D3DPT_TRIANGLESTRIP:
261             TRACE("TRIANGLE_STRIP\n");
262             primType = GL_TRIANGLE_STRIP;
263             NumVertexes = NumPrimitives + 2;
264             break;
265
266         case D3DPT_TRIANGLEFAN:
267             TRACE("TRIANGLE_FAN\n");
268             primType = GL_TRIANGLE_FAN;
269             NumVertexes = NumPrimitives + 2;
270             break;
271
272         default:
273             FIXME("Unhandled primitive\n");
274             break;
275         }
276
277         /* Fixme, Ideally, only use this per-vertex code for software HAL 
278            but until opengl supports all the functions returned to setup 
279            vertex arrays, we need to drop down to the slow mechanism for  
280            certain functions                                              */
281
282         if (isPtSize || isDiffuse || useVertexShaderFunction==TRUE || (numBlends > 0)) {
283             TRACE("Using slow per-vertex code\n");
284
285             /* Enable this one to be able to debug what is going on, but it is slower
286                than the pointer/array version                                          */
287             VTRACE(("glBegin(%x)\n", primType));
288             glBegin(primType);
289
290             /* Draw the primitives */
291             curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
292
293             for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
294
295                 if (!isIndexed) {
296                     curPos = curVtx;
297                 } else {
298                     if (idxBytes == 2) {
299                         VTRACE(("Idx for vertex %d = %d = %d\n", vx_index, pIdxBufS[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
300                         curPos = curVtx + ((pIdxBufS[StartIdx+vx_index]) * skip);
301                     } else {
302                         VTRACE(("Idx for vertex %d = %ld = %d\n", vx_index, pIdxBufL[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
303                         curPos = curVtx + ((pIdxBufL[StartIdx+vx_index]) * skip);
304                     }
305                 }
306
307                 /* Work through the vertex buffer */
308                 x = *(float *)curPos;
309                 curPos = curPos + sizeof(float);
310                 y = *(float *)curPos;
311                 curPos = curPos + sizeof(float);
312                 z = *(float *)curPos;
313                 curPos = curPos + sizeof(float);
314                 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
315
316                 /* RHW follows, only if transformed */
317                 if (isRHW) {
318                     rhw = *(float *)curPos;
319                     curPos = curPos + sizeof(float);
320                     VTRACE(("rhw=%f\n", rhw));
321                 }
322
323                 /* Blending data */
324                 if (numBlends > 0) {
325                     UINT i;
326                     D3DSHADERVECTOR skippedBlend = { 0.0f, 0.0f, 0.0f, 0.0f};
327                     DWORD skippedBlendLastUByte4 = 0;
328
329                     for (i = 0; i < ((FALSE == isLastUByte4) ? numBlends : numBlends - 1); ++i) {
330                         ((float*)&skippedBlend)[i] =  *(float *)curPos; 
331                         curPos = curPos + sizeof(float);
332                     }
333
334                     if (isLastUByte4) {
335                         skippedBlendLastUByte4 =  *(DWORD*)curPos; 
336                         curPos = curPos + sizeof(DWORD);
337                     }
338                 }
339
340                 /* Vertex Normal Data (untransformed only) */
341                 if (normal) {
342                     nx = *(float *)curPos;
343                     curPos = curPos + sizeof(float);
344                     ny = *(float *)curPos;
345                     curPos = curPos + sizeof(float);
346                     nz = *(float *)curPos;
347                     curPos = curPos + sizeof(float);
348                     VTRACE(("nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
349                 }
350
351                 if (isPtSize) {
352                     ptSize = *(float *)curPos;
353                     VTRACE(("ptSize=%f\n", ptSize));
354                     curPos = curPos + sizeof(float);
355                 }
356
357                 if (isDiffuse) {
358                     diffuseColor = *(DWORD *)curPos;
359                     VTRACE(("diffuseColor=%lx\n", diffuseColor));
360                     curPos = curPos + sizeof(DWORD);
361                 }
362
363                 if (isSpecular) {
364                     specularColor = *(DWORD *)curPos;
365                     VTRACE(("specularColor=%lx\n", specularColor));
366                     curPos = curPos + sizeof(DWORD);
367                 }
368
369                 /* Texture coords */
370                 /* numTextures indicates the number of texture coordinates supplied */
371                 /* However, the first set may not be for stage 0 texture - it all   */
372                 /*   depends on D3DTSS_TEXCOORDINDEX.                               */
373                 /* The number of bytes for each coordinate set is based off         */
374                 /*   D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
375
376                 /* Initialize unused coords to unsupplied so we can check later */
377                 for (textureNo = numTextures; textureNo < 7; textureNo++) numCoords[textureNo] = -1;
378
379                 /* So, for each supplied texture extract the coords */
380                 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
381                                         
382                     numCoords[textureNo] = coordIdxInfo & 0x03;
383
384                     /* Always one set */
385                     s[textureNo] = *(float *)curPos;
386                     curPos = curPos + sizeof(float);
387                     if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
388                         t[textureNo] = *(float *)curPos;
389                         curPos = curPos + sizeof(float);
390                         if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
391                             r[textureNo] = *(float *)curPos;
392                             curPos = curPos + sizeof(float);
393                             if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
394                                 q[textureNo] = *(float *)curPos;
395                                 curPos = curPos + sizeof(float);
396                             }
397                         }
398                     }
399
400                     coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
401                 }
402
403                 /* Now use the appropriate set of texture indexes */
404                 for (textureNo = 0; textureNo < This->TextureUnits; ++textureNo) {
405
406                     if (!(This->isMultiTexture) && textureNo > 0) {
407                         FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
408                         continue ;
409                     }
410
411                     /* Query tex coords */
412                     if ((This->StateBlock->textures[textureNo] != NULL) && 
413                         (useVertexShaderFunction == FALSE)) {
414
415                         int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
416
417                         if (coordIdx > 7) {
418                             VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
419                         } else if (coordIdx >= numTextures) {
420                             VTRACE(("tex: %d - Skip tex coords, as requested higher than supplied\n", textureNo));
421                         } else {
422                             switch (numCoords[coordIdx]) {   /* Supply the provided texture coords */
423                             case D3DFVF_TEXTUREFORMAT1:
424                                 VTRACE(("tex:%d, s=%f\n", textureNo, s[coordIdx]));
425                                 if (This->isMultiTexture) {
426 #if defined(GL_VERSION_1_3)
427                                     glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s[coordIdx]);
428 #else
429                                     glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx]);
430 #endif
431                                 } else {
432                                     glTexCoord1f(s[coordIdx]);
433                                 }
434                                 break;
435                             case D3DFVF_TEXTUREFORMAT2:
436                                 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s[coordIdx], t[coordIdx]));
437                                 if (This->isMultiTexture) {
438 #if defined(GL_VERSION_1_3)
439                                     glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx]);
440 #else
441                                     glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx]);
442 #endif
443                                 } else {
444                                     glTexCoord2f(s[coordIdx], t[coordIdx]);
445                                 }
446                                 break;
447                             case D3DFVF_TEXTUREFORMAT3:
448                                 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s[coordIdx], t[coordIdx], r[coordIdx]));
449                                 if (This->isMultiTexture) {
450 #if defined(GL_VERSION_1_3)
451                                     glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx], r[coordIdx]);
452 #else
453                                     glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx], r[coordIdx]);
454 #endif
455                                 } else {
456                                     glTexCoord3f(s[coordIdx], t[coordIdx], r[coordIdx]);
457                                 }
458                                 break;
459                             case D3DFVF_TEXTUREFORMAT4:
460                                 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]));
461                                 if (This->isMultiTexture) {
462 #if defined(GL_VERSION_1_3)
463                                     glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
464 #else
465                                     glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
466 #endif
467                                 } else {
468                                     glTexCoord4f(s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
469                                 }
470                                 break;
471                             default:
472                                 FIXME("Should not get here as numCoords is two bits only (%x)!\n", numCoords[coordIdx]);
473                             }
474                         }
475                     }
476
477                 }
478
479                 /** if vertex shader program specified ... using it */
480                 if (TRUE == useVertexShaderFunction) {
481
482                     /**
483                      * this code must become the really 
484                      * vs input params init
485                      * 
486                      * because its possible to use input registers for anything
487                      * and some samples use registers for other things than they are
488                      * declared
489                      */
490
491                     /** 
492                      * no really valid declaration, user defined input register use 
493                      * so fill input registers as described in vertex shader declaration
494                      */
495                     IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, vertexBufData, StartVertexIndex,
496                                                               (!isIndexed) ? (vx_index * skip) : 
497                                                                              (idxBytes == 2) ? ((pIdxBufS[StartIdx + vx_index]) * skip) : 
498                                                                                                ((pIdxBufL[StartIdx + vx_index]) * skip));
499
500                     memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
501                     IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
502                     /*
503                     TRACE_VECTOR(vertex_shader->output.oPos);
504                     TRACE_VECTOR(vertex_shader->output.oD[0]);
505                     TRACE_VECTOR(vertex_shader->output.oD[1]);
506                     TRACE_VECTOR(vertex_shader->output.oT[0]);
507                     TRACE_VECTOR(vertex_shader->output.oT[1]);
508                     TRACE_VECTOR(vertex_shader->input.V[0]);
509                     TRACE_VECTOR(vertex_shader->data->C[0]);
510                     TRACE_VECTOR(vertex_shader->data->C[1]);
511                     TRACE_VECTOR(vertex_shader->data->C[2]);
512                     TRACE_VECTOR(vertex_shader->data->C[3]);
513                     TRACE_VECTOR(vertex_shader->data->C[4]);
514                     TRACE_VECTOR(vertex_shader->data->C[5]);
515                     TRACE_VECTOR(vertex_shader->data->C[6]);
516                     TRACE_VECTOR(vertex_shader->data->C[7]);
517                     */
518                     x = vertex_shader->output.oPos.x;
519                     y = vertex_shader->output.oPos.y;
520                     z = vertex_shader->output.oPos.z;
521
522                     if (1.0f != vertex_shader->output.oPos.w || isRHW) {
523                       rhw = vertex_shader->output.oPos.w;
524                     }
525                     /*diffuseColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[0]);*/
526                     glColor4fv((float*) &vertex_shader->output.oD[0]);
527
528                     /* Requires secondary color extensions to compile... */
529 #if defined(GL_VERSION_1_4)
530                     glSecondaryColor3fv((float*) &vertex_shader->output.oD[1]);
531                     checkGLcall("glSecondaryColor3fv");
532 #else
533                     if (checkGLSupport(EXT_SECONDARY_COLOR)) {
534                       /*specularColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[1]);*/
535                       /*GLExtCall(glSecondaryColor3fvEXT)((float*) &vertex_shader->output.oD[1]);*/
536                       /*checkGLcall("glSecondaryColor3fvEXT");*/
537                     }
538 #endif
539                     /** reupdate textures coords binding using vertex_shader->output.oT[0->3] */
540                     for (textureNo = 0; textureNo < 4; ++textureNo) {
541                         float s, t, r, q;
542
543                         if (!(This->isMultiTexture) && textureNo > 0) {
544                             FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
545                             continue ;
546                         }
547                         /* Query tex coords */
548                         if (This->StateBlock->textures[textureNo] != NULL) {
549                             switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
550                             case D3DRTYPE_TEXTURE:
551                                 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
552                                 s = vertex_shader->output.oT[textureNo].x;
553                                 t = vertex_shader->output.oT[textureNo].y;
554                                 VTRACE(("tex:%d, s,t=%f,%f\n", textureNo, s, t));
555                                 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
556                                     VTRACE(("Skip tex coords, as being system generated\n"));
557                                 } else {
558                                     if (This->isMultiTexture) {
559 #if defined(GL_VERSION_1_3)
560                                         glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
561 #else
562                                         glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
563 #endif
564                                         /*checkGLcall("glMultiTexCoord2fARB");*/
565                                     } else {
566                                         glTexCoord2f(s, t);
567                                         /*checkGLcall("gTexCoord2f");*/
568                                     }
569                                 }
570                                 break;
571
572                             case D3DRTYPE_VOLUMETEXTURE:
573                                 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
574                                 s = vertex_shader->output.oT[textureNo].x;
575                                 t = vertex_shader->output.oT[textureNo].y;
576                                 r = vertex_shader->output.oT[textureNo].z;
577                                 VTRACE(("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s, t, r));
578                                 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
579                                     VTRACE(("Skip tex coords, as being system generated\n"));
580                                 } else {
581                                     if (This->isMultiTexture) {
582 #if defined(GL_VERSION_1_3)
583                                         glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r); 
584 #else
585                                         glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r); 
586 #endif
587                                         /*checkGLcall("glMultiTexCoord2fARB");*/
588                                     } else {
589                                         glTexCoord3f(s, t, r);
590                                         /*checkGLcall("gTexCoord3f");*/
591                                     }
592                                 }
593                                 break;
594
595                             default:
596                                 /* Avoid compiler warnings, need these vars later for other textures */
597                                 r = 0.0f; q = 0.0f; 
598                                 FIXME("Unhandled texture type\n");
599                             }
600                         }
601                     }
602
603                     if (1.0f == rhw || rhw < 0.01f) {
604                         VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
605                         glVertex3f(x, y, z);
606                         /*checkGLcall("glVertex3f");*/
607                     } else {
608                         VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
609                         glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
610                         /*checkGLcall("glVertex4f");*/
611                     }
612                 } else { 
613                     /** 
614                      * FALSE == useVertexShaderFunction 
615                      *  using std FVF code
616                      */
617
618                     /* Handle these vertexes */
619                     if (isDiffuse) {
620                         glColor4ub((diffuseColor >> 16) & 0xFF,
621                                    (diffuseColor >>  8) & 0xFF,
622                                    (diffuseColor >>  0) & 0xFF,
623                                    (diffuseColor >> 24) & 0xFF);
624                         VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", 
625                               ((diffuseColor >> 16) & 0xFF) / 255.0f, 
626                               ((diffuseColor >>  8) & 0xFF) / 255.0f,
627                               ((diffuseColor >>  0) & 0xFF) / 255.0f, 
628                               ((diffuseColor >> 24) & 0xFF) / 255.0f));
629                     }
630
631                     if (normal) {
632                         VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f  /  glNormal:nx,ny,nz=%f,%f,%f\n", x,y,z,nx,ny,nz));
633                         glNormal3f(nx, ny, nz);
634                         glVertex3f(x, y, z);
635                     } else {
636                         if (1.0f == rhw || rhw < 0.01f) {
637                             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
638                             glVertex3f(x, y, z);
639                         } else {
640                             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
641                             glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
642                         }
643                     }
644                 }
645
646                 if (!isIndexed) {
647                     curVtx = curVtx + skip;
648                 }
649             }
650
651             glEnd();
652             checkGLcall("glEnd and previous calls");
653
654         } else {
655             TRACE("Using fast vertex array code\n");
656
657             /* Faster version, harder to debug */
658             /* Shuffle to the beginning of the vertexes to render and index from there */
659             curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
660             curPos = curVtx;
661
662             /* Set up the vertex pointers */
663             if (isRHW) {
664                glVertexPointer(4, GL_FLOAT, skip, curPos);
665                checkGLcall("glVertexPointer(4, ...)");
666                curPos += 4 * sizeof(float);
667             } else {
668                glVertexPointer(3, GL_FLOAT, skip, curPos);
669                checkGLcall("glVertexPointer(3, ...)");
670                curPos += 3 * sizeof(float);
671             }
672             glEnableClientState(GL_VERTEX_ARRAY);
673             checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
674  
675             if (numBlends > 0) {
676                /* no such functionality in the fixed function GL pipeline */
677                /* FIXME: Wont get here as will drop to slow method        */
678                /* FIXME("Cannot handle blending data here in openGl\n");*/
679                if (checkGLSupport(ARB_VERTEX_BLEND)) {
680                   FIXME("TODO\n");
681                } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
682                   FIXME("TODO\n");
683                   /*
684                   GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos); 
685                   checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
686                   glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
687                   checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
688                   */
689                   curPos += numBlends * sizeof(float);
690                } else {
691                   FIXME("unsupported blending in openGl\n");
692                }
693             } else {
694                if (checkGLSupport(ARB_VERTEX_BLEND)) {
695                   FIXME("TODO\n");
696                } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
697                   FIXME("TODO\n");
698                   /*
699                   glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
700                   checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
701                   */
702                }
703             }
704
705  
706             if (normal) {
707                 glNormalPointer(GL_FLOAT, skip, curPos);
708                 checkGLcall("glNormalPointer");
709                 glEnableClientState(GL_NORMAL_ARRAY);
710                 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
711                 curPos += 3 * sizeof(float);
712             } else {
713                 glDisableClientState(GL_NORMAL_ARRAY);
714                 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
715                 glNormal3f(0, 0, 1);
716                 checkGLcall("glNormal3f(0, 0, 1)");
717             }
718  
719             if (isPtSize) {
720                 /* no such functionality in the fixed function GL pipeline */
721                 /* FIXME: Wont get here as will drop to slow method        */
722                 FIXME("Cannot change ptSize here in openGl\n");
723                 curPos = curPos + sizeof(float);
724             }
725
726             if (isDiffuse) {
727                 glColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
728                 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
729                 glEnableClientState(GL_COLOR_ARRAY);
730                 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
731                 curPos += sizeof(DWORD);
732             }
733             else {
734                 glDisableClientState(GL_COLOR_ARRAY);
735                 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
736                 glColor4f(1, 1, 1, 1);
737                 checkGLcall("glColor4f(1, 1, 1, 1)");
738             }
739
740             /* Requires secondary color extensions to compile... */
741             if (isSpecular) {
742 #if defined(GL_VERSION_1_4)
743                 glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
744                 checkGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos)");
745                 glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
746                 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
747 #else
748 # if 0
749                 /* FIXME: check for GL_EXT_secondary_color */
750                 glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos);
751                 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos)");
752                 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
753                 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
754 # endif
755 #endif
756                 curPos += sizeof(DWORD);
757             } else {
758 #if defined(GL_VERSION_1_4)
759                 glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
760                 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
761                 glSecondaryColor3f(0, 0, 0);
762                 checkGLcall("glSecondaryColor3f(0, 0, 0)");
763 #else
764 #if 0
765                 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
766                 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
767                 glSecondaryColor3fEXT(0, 0, 0);
768                 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
769 #endif
770 #endif
771             }
772
773             /* Texture coords */
774             /* numTextures indicates the number of texture coordinates supplied */
775             /* However, the first set may not be for stage 0 texture - it all   */
776             /*   depends on D3DTSS_TEXCOORDINDEX.                               */
777             /* The number of bytes for each coordinate set is based off         */
778             /*   D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
779
780             /* Initialize unused coords to unsupplied so we can check later */
781             for (textureNo = numTextures; textureNo < 7; textureNo++) coordPtr[textureNo] = NULL;
782
783             /* So, for each supplied texture extract the coords */
784             for (textureNo = 0; textureNo < numTextures; ++textureNo) {
785                 
786                 numCoords[textureNo] = coordIdxInfo & 0x03;
787                 coordPtr[textureNo] = curPos;
788
789                 /* Always one set */
790                 curPos = curPos + sizeof(float);
791                 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
792                     curPos = curPos + sizeof(float);
793                     if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
794                         curPos = curPos + sizeof(float);
795                         if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
796                             curPos = curPos + sizeof(float);
797                         }
798                     }
799                 }
800                 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
801             }
802
803             /* Now use the appropriate set of texture indexes */
804             for (textureNo = 0; textureNo < This->TextureUnits; ++textureNo) {
805
806                 if (!(This->isMultiTexture) && textureNo > 0) {
807                     FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
808                     continue ;
809                 }
810
811                 /* Query tex coords */
812                 if ((This->StateBlock->textures[textureNo] != NULL) && (useVertexShaderFunction == FALSE)) {
813                     int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
814
815                     if (coordIdx > 7) {
816                         VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
817                     } else {
818                         int numFloats = 0;
819 #if defined(GL_VERSION_1_3)
820                         glClientActiveTexture(GL_TEXTURE0 + textureNo);
821 #else
822                         glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
823 #endif
824                         switch (numCoords[coordIdx]) {   /* Supply the provided texture coords */
825                         case D3DFVF_TEXTUREFORMAT1: numFloats = 1; break;
826                         case D3DFVF_TEXTUREFORMAT2: numFloats = 2; break;
827                         case D3DFVF_TEXTUREFORMAT3: numFloats = 3; break;
828                         case D3DFVF_TEXTUREFORMAT4: numFloats = 4; break;
829                         default: numFloats = 0; break;           
830                         }
831                             
832                         if (numFloats == 0 || coordIdx >= numTextures) {
833                             VTRACE(("Skipping as invalid request - numfloats=%d, coordIdx=%d, numTextures=%d\n", numFloats, coordIdx, numTextures));
834                             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
835                             checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
836                         } else {
837                             VTRACE(("tex: %d, ptr=%p, numcoords=%d\n", textureNo, coordPtr[coordIdx], numFloats));
838                             glTexCoordPointer(numFloats, GL_FLOAT, skip, coordPtr[coordIdx]);
839                             checkGLcall("glTexCoordPointer(x, ...)");
840                             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
841                             checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
842                         }
843                     }
844                 }
845             }
846
847             /* Finally do the drawing */
848             if (isIndexed) {
849  
850                 TRACE("glElements(%x, %d, %d, ...)\n", primType, NumVertexes, minIndex);
851                 if (idxBytes==2) {
852 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
853                     glDrawElements(primType, NumVertexes, GL_UNSIGNED_SHORT,
854                                    (char *)idxData+(2 * StartIdx));
855 #else
856                     glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
857                                         GL_UNSIGNED_SHORT, (char *)idxData+(2 * StartIdx));
858 #endif
859                 } else {
860 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
861                     glDrawElements(primType, NumVertexes, GL_UNSIGNED_INT,
862                                    (char *)idxData+(4 * StartIdx));
863 #else
864                     glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
865                                         GL_UNSIGNED_INT, (char *)idxData+(2 * StartIdx));
866 #endif
867                 }
868                 checkGLcall("glDrawRangeElements");
869
870             } else {
871  
872                 /* Note first is now zero as we shuffled along earlier */
873                 TRACE("glDrawArrays(%x, %ld, %d)\n", primType, StartIdx, NumVertexes);
874                 glDrawArrays(primType, 0, NumVertexes);
875                 checkGLcall("glDrawArrays");
876  
877             }
878         }
879
880         /* If no normals, restore previous lighting state */
881         if (!normal) {
882             if (isLightingOn) glEnable(GL_LIGHTING);
883             else glDisable(GL_LIGHTING);
884             TRACE("Restored lighting to original state\n");
885         }
886
887     }
888     LEAVE_GL();
889
890     TRACE("glEnd\n");
891 }
892
893 /*
894     Simple utility routines used for dx -> gl mapping of byte formats
895  */
896 SHORT bytesPerPixel(D3DFORMAT fmt) {
897     SHORT retVal;
898
899     switch (fmt) {
900     /* color buffer */
901     case D3DFMT_A4R4G4B4:         retVal = 2; break;
902     case D3DFMT_A8R8G8B8:         retVal = 4; break;
903     case D3DFMT_X8R8G8B8:         retVal = 4; break;
904     case D3DFMT_R8G8B8:           retVal = 3; break;
905     case D3DFMT_R5G6B5:           retVal = 2; break;
906     case D3DFMT_A1R5G5B5:         retVal = 2; break;
907     /* depth/stencil buffer */
908     case D3DFMT_D16_LOCKABLE:     retVal = 2; break;
909     case D3DFMT_D32:              retVal = 4; break;
910     case D3DFMT_D15S1:            retVal = 2; break;
911     case D3DFMT_D24S8:            retVal = 4; break;
912     case D3DFMT_D16:              retVal = 2; break;
913     case D3DFMT_D24X8:            retVal = 4; break;
914     case D3DFMT_D24X4S4:          retVal = 4; break;
915     /* unknown */                                 
916     case D3DFMT_UNKNOWN:
917         /* Guess at the highest value of the above */
918         TRACE("D3DFMT_UNKNOWN - Guessing at 4 bytes/pixel %d\n", fmt);
919         retVal = 4;
920         break;
921     default:
922         FIXME("Unhandled fmt %d\n", fmt);
923         retVal = 4;
924     }
925     TRACE("bytes/Pxl for fmt %d = %d\n", fmt, retVal);
926     return retVal;
927 }
928
929 GLint fmt2glintFmt(D3DFORMAT fmt) {
930     GLint retVal;
931
932     switch (fmt) {
933     case D3DFMT_A4R4G4B4:         retVal = GL_RGBA4; break;
934     case D3DFMT_A8R8G8B8:         retVal = GL_RGBA8; break;
935     case D3DFMT_X8R8G8B8:         retVal = GL_RGB8; break;
936     case D3DFMT_R8G8B8:           retVal = GL_RGB8; break;
937     case D3DFMT_R5G6B5:           retVal = GL_RGB5; break; /* fixme: internal format 6 for g? */
938     case D3DFMT_A1R5G5B5:         retVal = GL_RGB5_A1; break;
939     default:
940         FIXME("Unhandled fmt %d\n", fmt);
941         retVal = 4;
942     }
943     TRACE("fmt2glintFmt for fmt %d = %x\n", fmt, retVal);
944     return retVal;
945 }
946 GLenum fmt2glFmt(D3DFORMAT fmt) {
947     GLenum retVal;
948
949     switch (fmt) {
950     case D3DFMT_A4R4G4B4:         retVal = GL_BGRA; break;
951     case D3DFMT_A8R8G8B8:         retVal = GL_BGRA; break;
952     case D3DFMT_X8R8G8B8:         retVal = GL_BGRA; break;
953     case D3DFMT_R8G8B8:           retVal = GL_BGR; break;
954     case D3DFMT_R5G6B5:           retVal = GL_RGB; break;
955     case D3DFMT_A1R5G5B5:         retVal = GL_BGRA; break;
956     default:
957         FIXME("Unhandled fmt %d\n", fmt);
958         retVal = 4;
959     }
960     TRACE("fmt2glFmt for fmt %d = %x\n", fmt, retVal);
961     return retVal;
962 }
963 DWORD fmt2glType(D3DFORMAT fmt) {
964     GLenum retVal;
965
966     switch (fmt) {
967     case D3DFMT_A4R4G4B4:         retVal = GL_UNSIGNED_SHORT_4_4_4_4_REV; break;
968     case D3DFMT_A8R8G8B8:         retVal = GL_UNSIGNED_BYTE; break;
969     case D3DFMT_X8R8G8B8:         retVal = GL_UNSIGNED_BYTE; break;
970     case D3DFMT_R5G6B5:           retVal = GL_UNSIGNED_SHORT_5_6_5_REV; break;
971     case D3DFMT_R8G8B8:           retVal = GL_UNSIGNED_BYTE; break;
972     case D3DFMT_A1R5G5B5:         retVal = GL_UNSIGNED_SHORT_1_5_5_5_REV; break;
973     default:
974         FIXME("Unhandled fmt %d\n", fmt);
975         retVal = 4;
976     }
977     TRACE("fmt2glType for fmt %d = %x\n", fmt, retVal);
978     return retVal;
979 }
980
981 int SOURCEx_RGB_EXT(DWORD arg) {
982     switch(arg) {
983     case D3DTSS_COLORARG0: return GL_SOURCE2_RGB_EXT;
984     case D3DTSS_COLORARG1: return GL_SOURCE0_RGB_EXT;
985     case D3DTSS_COLORARG2: return GL_SOURCE1_RGB_EXT;
986     case D3DTSS_ALPHAARG0:
987     case D3DTSS_ALPHAARG1:
988     case D3DTSS_ALPHAARG2:
989     default:
990         FIXME("Invalid arg %ld\n", arg);
991         return GL_SOURCE0_RGB_EXT;
992     }
993 }
994 int OPERANDx_RGB_EXT(DWORD arg) {
995     switch(arg) {
996     case D3DTSS_COLORARG0: return GL_OPERAND2_RGB_EXT;
997     case D3DTSS_COLORARG1: return GL_OPERAND0_RGB_EXT;
998     case D3DTSS_COLORARG2: return GL_OPERAND1_RGB_EXT;
999     case D3DTSS_ALPHAARG0:
1000     case D3DTSS_ALPHAARG1:
1001     case D3DTSS_ALPHAARG2:
1002     default:
1003         FIXME("Invalid arg %ld\n", arg);
1004         return GL_OPERAND0_RGB_EXT;
1005     }
1006 }
1007 int SOURCEx_ALPHA_EXT(DWORD arg) {
1008     switch(arg) {
1009     case D3DTSS_ALPHAARG0:  return GL_SOURCE2_ALPHA_EXT;
1010     case D3DTSS_ALPHAARG1:  return GL_SOURCE0_ALPHA_EXT;
1011     case D3DTSS_ALPHAARG2:  return GL_SOURCE1_ALPHA_EXT;
1012     case D3DTSS_COLORARG0:
1013     case D3DTSS_COLORARG1:
1014     case D3DTSS_COLORARG2:
1015     default:
1016         FIXME("Invalid arg %ld\n", arg);
1017         return GL_SOURCE0_ALPHA_EXT;
1018     }
1019 }
1020 int OPERANDx_ALPHA_EXT(DWORD arg) {
1021     switch(arg) {
1022     case D3DTSS_ALPHAARG0:  return GL_OPERAND2_ALPHA_EXT;
1023     case D3DTSS_ALPHAARG1:  return GL_OPERAND0_ALPHA_EXT;
1024     case D3DTSS_ALPHAARG2:  return GL_OPERAND1_ALPHA_EXT;
1025     case D3DTSS_COLORARG0:
1026     case D3DTSS_COLORARG1:
1027     case D3DTSS_COLORARG2:
1028     default:
1029         FIXME("Invalid arg %ld\n", arg);
1030         return GL_OPERAND0_ALPHA_EXT;
1031     }
1032 }
1033 GLenum StencilOp(DWORD op) {
1034     switch(op) {                
1035     case D3DSTENCILOP_KEEP    : return GL_KEEP;
1036     case D3DSTENCILOP_ZERO    : return GL_ZERO;
1037     case D3DSTENCILOP_REPLACE : return GL_REPLACE;
1038     case D3DSTENCILOP_INCRSAT : return GL_INCR;
1039     case D3DSTENCILOP_DECRSAT : return GL_DECR;
1040     case D3DSTENCILOP_INVERT  : return GL_INVERT;
1041     case D3DSTENCILOP_INCR    : FIXME("Unsupported stencil op D3DSTENCILOP_INCR\n");
1042                                 return GL_INCR; /* Fixme - needs to support wrap */
1043     case D3DSTENCILOP_DECR    : FIXME("Unsupported stencil op D3DSTENCILOP_DECR\n");
1044                                 return GL_DECR; /* Fixme - needs to support wrap */
1045     default:
1046         FIXME("Invalid stencil op %ld\n", op);
1047         return GL_ALWAYS;
1048     }
1049 }
1050
1051 /**
1052  * @nodoc: todo
1053  */
1054 void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand) 
1055 {
1056   BOOL isAlphaReplicate = FALSE;
1057   BOOL isComplement     = FALSE;
1058   
1059   *operand = GL_SRC_COLOR;
1060   *source = GL_TEXTURE;
1061   
1062   /* Catch alpha replicate */
1063   if (iValue & D3DTA_ALPHAREPLICATE) {
1064     iValue = iValue & ~D3DTA_ALPHAREPLICATE;
1065     isAlphaReplicate = TRUE;
1066   }
1067   
1068   /* Catch Complement */
1069   if (iValue & D3DTA_COMPLEMENT) {
1070     iValue = iValue & ~D3DTA_COMPLEMENT;
1071     isComplement = TRUE;
1072   }
1073   
1074   /* Calculate the operand */
1075   if (isAlphaReplicate && !isComplement) {
1076     *operand = GL_SRC_ALPHA;
1077   } else if (isAlphaReplicate && isComplement) {
1078     *operand = GL_ONE_MINUS_SRC_ALPHA;
1079   } else if (isComplement) {
1080     if (isAlphaArg) {
1081       *operand = GL_ONE_MINUS_SRC_ALPHA;
1082     } else {
1083       *operand = GL_ONE_MINUS_SRC_COLOR;
1084     }
1085   } else {
1086     if (isAlphaArg) {
1087       *operand = GL_SRC_ALPHA;
1088     } else {
1089       *operand = GL_SRC_COLOR;
1090     }
1091   }
1092   
1093   /* Calculate the source */
1094   switch (iValue & D3DTA_SELECTMASK) {
1095   case D3DTA_CURRENT:   *source  = GL_PREVIOUS_EXT;
1096     break;
1097   case D3DTA_DIFFUSE:   *source  = GL_PRIMARY_COLOR_EXT;
1098     break;
1099   case D3DTA_TEXTURE:   *source  = GL_TEXTURE;
1100     break;
1101   case D3DTA_TFACTOR:   *source  = GL_CONSTANT_EXT;
1102     break;
1103   case D3DTA_SPECULAR:
1104     /**
1105      * According to the GL_ARB_texture_env_combine specs, SPECULAR is 'Secondary color' and
1106      * isnt supported until base GL supports it
1107      * There is no concept of temp registers as far as I can tell
1108      */
1109
1110   default:
1111     FIXME("Unrecognized or unhandled texture arg %ld\n", iValue);
1112     *source = GL_TEXTURE;
1113   }
1114 }
1115
1116
1117 /* Apply the current values to the specified texture stage */
1118 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
1119     ICOM_THIS(IDirect3DDevice8Impl,iface);
1120     int i=0;
1121     float col[4];
1122
1123     /* Make appropriate texture active */
1124     if (This->isMultiTexture) {
1125 #if defined(GL_VERSION_1_3)
1126         glActiveTexture(GL_TEXTURE0 + Stage);
1127 #else
1128         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
1129 #endif
1130         checkGLcall("glActiveTextureARB");
1131     } else if (Stage > 0) {
1132         FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
1133     }
1134
1135     TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
1136     for (i=1; i<HIGHEST_TEXTURE_STATE; i++) {
1137         IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
1138     }
1139
1140     /* Note the D3DRS value applies to all textures, but GL has one
1141        per texture, so apply it now ready to be used!               */
1142     col[0] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR]>> 16) & 0xFF) / 255.0;
1143     col[1] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 8 ) & 0xFF) / 255.0;
1144     col[2] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 0 ) & 0xFF) / 255.0;
1145     col[3] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 24 ) & 0xFF) / 255.0;
1146     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1147     checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1148
1149     TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
1150 }
1151
1152 /* IDirect3D IUnknown parts follow: */
1153 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
1154 {
1155     ICOM_THIS(IDirect3DDevice8Impl,iface);
1156
1157     if (IsEqualGUID(riid, &IID_IUnknown)
1158         || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
1159         IDirect3DDevice8Impl_AddRef(iface);
1160         *ppobj = This;
1161         return D3D_OK;
1162     }
1163
1164     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
1165     return E_NOINTERFACE;
1166 }
1167
1168 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
1169     ICOM_THIS(IDirect3DDevice8Impl,iface);
1170     TRACE("(%p) : AddRef from %ld\n", This, This->ref);
1171     return ++(This->ref);
1172 }
1173
1174 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
1175     ICOM_THIS(IDirect3DDevice8Impl,iface);
1176     ULONG ref = --This->ref;
1177     TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
1178     if (ref == 0) {
1179         HeapFree(GetProcessHeap(), 0, This);
1180     }
1181     return ref;
1182 }
1183
1184 /* IDirect3DDevice Interface follow: */
1185 HRESULT  WINAPI  IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
1186     ICOM_THIS(IDirect3DDevice8Impl,iface);
1187     TRACE("(%p) : stub\n", This);    /* No way of notifying yet! */
1188     return D3D_OK;
1189 }
1190
1191 UINT     WINAPI  IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
1192     ICOM_THIS(IDirect3DDevice8Impl,iface);
1193     TRACE("(%p) : stub, emulating 32Mb for now\n", This);
1194     /*
1195      * pretend we have 32MB of any type of memory queried.
1196      */
1197     return (1024*1024*32);
1198 }
1199
1200 HRESULT  WINAPI  IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
1201     ICOM_THIS(IDirect3DDevice8Impl,iface);
1202     FIXME("(%p) : stub\n", This);    return D3D_OK;
1203 }
1204 HRESULT  WINAPI  IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
1205     ICOM_THIS(IDirect3DDevice8Impl,iface);
1206     TRACE("(%p) : returning %p\n", This, This->direct3d8);
1207
1208     /* Inc ref count */
1209     IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
1210
1211     *ppD3D8 = (IDirect3D8 *)This->direct3d8;
1212     return D3D_OK;
1213 }
1214 HRESULT  WINAPI  IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
1215     ICOM_THIS(IDirect3DDevice8Impl,iface);
1216     FIXME("(%p) : stub, calling idirect3d for now\n", This);
1217     IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
1218     return D3D_OK;
1219 }
1220 HRESULT  WINAPI  IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
1221
1222     HDC hdc;
1223     int bpp = 0;
1224
1225     ICOM_THIS(IDirect3DDevice8Impl,iface);
1226     pMode->Width        = GetSystemMetrics(SM_CXSCREEN);
1227     pMode->Height       = GetSystemMetrics(SM_CYSCREEN);
1228     pMode->RefreshRate  = 85; /*FIXME: How to identify? */
1229
1230     hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1231     bpp = GetDeviceCaps(hdc, BITSPIXEL);
1232     DeleteDC(hdc);
1233
1234     switch (bpp) {
1235     case  8: pMode->Format       = D3DFMT_R8G8B8; break;
1236     case 16: pMode->Format       = D3DFMT_R5G6B5; break;
1237     case 24: pMode->Format       = D3DFMT_R8G8B8; break;
1238     case 32: pMode->Format       = D3DFMT_A8R8G8B8; break;
1239     default: 
1240        FIXME("Unrecognized display mode format\n");
1241        pMode->Format       = D3DFMT_UNKNOWN;
1242     }
1243
1244     FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%d)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, pMode->Format);
1245     return D3D_OK;
1246 }
1247 HRESULT  WINAPI  IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
1248     ICOM_THIS(IDirect3DDevice8Impl,iface);
1249     TRACE("(%p) copying to %p\n", This, pParameters);    
1250     memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
1251     return D3D_OK;
1252 }
1253 HRESULT  WINAPI  IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
1254     ICOM_THIS(IDirect3DDevice8Impl,iface);
1255     FIXME("(%p) : stub\n", This);    return D3D_OK;
1256 }
1257 void     WINAPI  IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace,DWORD Flags) {
1258     ICOM_THIS(IDirect3DDevice8Impl,iface);
1259     FIXME("(%p) : stub\n", This);    return;
1260 }
1261 BOOL     WINAPI  IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
1262     ICOM_THIS(IDirect3DDevice8Impl,iface);
1263     FIXME("(%p) : stub\n", This);    return D3D_OK;
1264 }
1265 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
1266     ICOM_THIS(IDirect3DDevice8Impl,iface);
1267     FIXME("(%p) : stub\n", This);    
1268     *pSwapChain = NULL;
1269     return D3D_OK;
1270 }
1271 HRESULT  WINAPI  IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
1272     ICOM_THIS(IDirect3DDevice8Impl,iface);
1273     FIXME("(%p) : stub\n", This);    return D3D_OK;
1274 }
1275 HRESULT  WINAPI  IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
1276     ICOM_THIS(IDirect3DDevice8Impl,iface);
1277     TRACE("(%p) : complete stub!\n", This);
1278
1279     ENTER_GL();
1280
1281     glXSwapBuffers(This->display, This->win);
1282     checkGLcall("glXSwapBuffers");
1283
1284     LEAVE_GL();
1285
1286     return D3D_OK;
1287 }
1288 HRESULT  WINAPI  IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
1289     ICOM_THIS(IDirect3DDevice8Impl,iface);
1290     *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
1291     TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
1292
1293     if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
1294         FIXME("Only one backBuffer currently supported\n");
1295         return D3DERR_INVALIDCALL;
1296     }
1297
1298     /* Note inc ref on returned surface */
1299     IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
1300
1301     return D3D_OK;
1302 }
1303 HRESULT  WINAPI  IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
1304     ICOM_THIS(IDirect3DDevice8Impl,iface);
1305     FIXME("(%p) : stub\n", This);    
1306     return D3D_OK;
1307 }
1308 void     WINAPI  IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags,CONST D3DGAMMARAMP* pRamp) {
1309     ICOM_THIS(IDirect3DDevice8Impl,iface);
1310     FIXME("(%p) : stub\n", This);    return;
1311 }
1312 void     WINAPI  IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
1313     ICOM_THIS(IDirect3DDevice8Impl,iface);
1314     FIXME("(%p) : stub\n", This);    return;
1315 }
1316 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
1317                                                     D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture8** ppTexture) {
1318     IDirect3DTexture8Impl *object;
1319     int i;
1320     UINT tmpW;
1321     UINT tmpH;
1322
1323     ICOM_THIS(IDirect3DDevice8Impl,iface);
1324
1325     /* Allocate the storage for the device */
1326     TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, Pool);
1327     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
1328     object->lpVtbl = &Direct3DTexture8_Vtbl;
1329     object->Device = This;
1330     /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->device);*/
1331     object->ResourceType = D3DRTYPE_TEXTURE;
1332     object->ref = 1;
1333     object->width = Width;
1334     object->height = Height;
1335     object->levels = Levels;
1336     object->usage = Usage;
1337     object->format = Format;
1338
1339
1340     /* Calculate levels for mip mapping */
1341     if (Levels == 0) {
1342         object->levels++;
1343         tmpW = Width;
1344         tmpH = Height;
1345         while (tmpW > 1 && tmpH > 1) {
1346             tmpW = max(1, tmpW / 2);
1347             tmpH = max(1, tmpH / 2);
1348             object->levels++;
1349         }
1350         TRACE("Calculated levels = %d\n", object->levels);
1351     }
1352
1353     /* Generate all the surfaces */
1354     tmpW = Width;
1355     tmpH = Height;
1356     for (i = 0; i < object->levels; i++) 
1357     {
1358         IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
1359         object->surfaces[i]->Container = (IUnknown*) object;
1360         /*IUnknown_AddRef(object->surfaces[i]->Container);*/
1361         object->surfaces[i]->myDesc.Usage = Usage;
1362         object->surfaces[i]->myDesc.Pool = Pool ;
1363
1364         TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
1365         tmpW = max(1, tmpW / 2);
1366         tmpH = max(1, tmpH / 2);
1367     }
1368
1369     *ppTexture = (LPDIRECT3DTEXTURE8) object;
1370     return D3D_OK;
1371 }
1372 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface, UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture8** ppVolumeTexture) {
1373
1374     IDirect3DVolumeTexture8Impl *object;
1375     int i;
1376     UINT tmpW;
1377     UINT tmpH;
1378     UINT tmpD;
1379
1380     ICOM_THIS(IDirect3DDevice8Impl,iface);
1381
1382     /* Allocate the storage for it */
1383     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, Width, Height, Depth, Levels, Usage, Format, Pool);
1384     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
1385     object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
1386     object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
1387     object->Device = This;
1388     /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1389     object->ref = 1;
1390
1391     object->width = Width;
1392     object->height = Height;
1393     object->depth = Depth;
1394     object->levels = Levels;
1395     object->usage = Usage;
1396     object->format = Format;
1397
1398     /* Calculate levels for mip mapping */
1399     if (Levels == 0) {
1400         object->levels++;
1401         tmpW = Width;
1402         tmpH = Height;
1403         tmpD = Depth;
1404         while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
1405             tmpW = max(1, tmpW / 2);
1406             tmpH = max(1, tmpH / 2);
1407             tmpD = max(1, tmpD / 2);
1408             object->levels++;
1409         }
1410         TRACE("Calculated levels = %d\n", object->levels);
1411     }
1412
1413     /* Generate all the surfaces */
1414     tmpW = Width;
1415     tmpH = Height;
1416     tmpD = Depth;
1417
1418     for (i = 0; i < object->levels; i++) 
1419     {
1420         IDirect3DVolume8Impl *volume;
1421
1422         /* Create the volume - No entry point for this seperately?? */
1423         volume  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
1424         object->volumes[i] = (IDirect3DVolume8Impl *) volume;
1425
1426         volume->lpVtbl = &Direct3DVolume8_Vtbl;
1427         volume->Device = This;
1428         /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) volume->Device);*/
1429         volume->ResourceType = D3DRTYPE_VOLUME;
1430         volume->Container = (IUnknown*) object;
1431         /*IUnknown_AddRef(volume->Container);*/ 
1432         volume->ref = 1;
1433
1434         volume->myDesc.Width  = Width;
1435         volume->myDesc.Height = Height;
1436         volume->myDesc.Depth  = Depth;
1437         volume->myDesc.Format = Format;
1438         volume->myDesc.Type   = D3DRTYPE_VOLUME;
1439         volume->myDesc.Pool   = Pool;
1440         volume->myDesc.Usage  = Usage;
1441         volume->bytesPerPixel   = bytesPerPixel(Format);
1442         volume->myDesc.Size     = (Width * volume->bytesPerPixel) * Height * Depth;
1443         volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
1444
1445         TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Depth, Format, 
1446                   volume, volume->allocatedMemory, volume->myDesc.Size);
1447
1448         tmpW = max(1, tmpW / 2);
1449         tmpH = max(1, tmpH / 2);
1450         tmpD = max(1, tmpD / 2);
1451     }
1452
1453     *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
1454     return D3D_OK;
1455 }
1456 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
1457
1458     IDirect3DCubeTexture8Impl *object;
1459     ICOM_THIS(IDirect3DDevice8Impl,iface);
1460     int i,j;
1461     UINT tmpW;
1462
1463     /* Allocate the storage for it */
1464     TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, EdgeLength, Levels, Usage, Format, Pool);
1465     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
1466     object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
1467     object->ref = 1;
1468     object->Device = This;
1469     /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1470     object->ResourceType = D3DRTYPE_CUBETEXTURE;
1471
1472     object->edgeLength = EdgeLength;
1473     object->levels = Levels;
1474     object->usage = Usage;
1475     object->format = Format;
1476
1477     /* Calculate levels for mip mapping */
1478     if (Levels == 0) {
1479         object->levels++;
1480         tmpW = EdgeLength;
1481         while (tmpW > 1) {
1482             tmpW = max(1, tmpW / 2);
1483             object->levels++;
1484         }
1485         TRACE("Calculated levels = %d\n", object->levels);
1486     }
1487
1488     /* Generate all the surfaces */
1489     tmpW = EdgeLength;
1490     for (i = 0; i < object->levels; i++) 
1491     {
1492         /* Create the 6 faces */
1493         for (j = 0; j < 6; j++) {
1494            IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
1495            object->surfaces[j][i]->Container = (IUnknown*) object;
1496            /*IUnknown_AddRef(object->surfaces[j][i]->Container);*/
1497            object->surfaces[j][i]->myDesc.Usage = Usage;
1498            object->surfaces[j][i]->myDesc.Pool = Pool;
1499
1500            TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
1501            tmpW = max(1, tmpW / 2);
1502         }
1503     }
1504
1505     TRACE("(%p) : Iface@%p\n", This, object);
1506     *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8)object;
1507     return D3D_OK;
1508 }
1509 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
1510     IDirect3DVertexBuffer8Impl *object;
1511
1512     ICOM_THIS(IDirect3DDevice8Impl,iface);
1513
1514     /* Allocate the storage for the device */
1515     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
1516     object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
1517     object->Device = This;
1518     /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1519     object->ResourceType = D3DRTYPE_VERTEXBUFFER;
1520     object->ref = 1;
1521     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
1522     object->currentDesc.Usage = Usage;
1523     object->currentDesc.Pool  = Pool;
1524     object->currentDesc.FVF   = FVF;
1525     object->currentDesc.Size  = Size;
1526
1527     TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
1528
1529     *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8)object;
1530
1531     return D3D_OK;
1532 }
1533 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
1534     IDirect3DIndexBuffer8Impl *object;
1535
1536     ICOM_THIS(IDirect3DDevice8Impl,iface);
1537     TRACE("(%p) : Len=%d, Use=%lx, Format=%x, Pool=%d\n", This, Length, Usage, Format, Pool);
1538
1539     /* Allocate the storage for the device */
1540     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
1541     object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
1542     object->Device = This;
1543     /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1544     object->ref = 1;
1545     object->ResourceType = D3DRTYPE_INDEXBUFFER;
1546
1547     object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
1548     object->currentDesc.Usage = Usage;
1549     object->currentDesc.Pool  = Pool;
1550     object->currentDesc.Format  = Format;
1551     object->currentDesc.Size  = Length;
1552
1553     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
1554
1555     TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
1556
1557     *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8)object;
1558
1559     return D3D_OK;
1560 }
1561 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
1562     IDirect3DSurface8Impl *object;
1563
1564     ICOM_THIS(IDirect3DDevice8Impl,iface);
1565     
1566     object  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1567     if (NULL == object) {
1568       *ppSurface = NULL;
1569       return D3DERR_OUTOFVIDEOMEMORY;
1570     }
1571     *ppSurface = (LPDIRECT3DSURFACE8) object;
1572     object->lpVtbl = &Direct3DSurface8_Vtbl;
1573     object->Device = This;
1574     /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1575     object->ResourceType = D3DRTYPE_SURFACE;
1576     object->Container = (IUnknown*) This;
1577     /*IUnknown_AddRef(object->Container);*/
1578
1579     object->ref = 1;
1580     object->myDesc.Width  = Width;
1581     object->myDesc.Height = Height;
1582     object->myDesc.Format = Format;
1583     object->myDesc.Type = D3DRTYPE_SURFACE;
1584     object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
1585     object->myDesc.Pool = D3DPOOL_DEFAULT;
1586     object->myDesc.MultiSampleType = MultiSample;
1587     object->bytesPerPixel = bytesPerPixel(Format);
1588     object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1589     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1590     object->lockable = Lockable;
1591     object->locked = FALSE;
1592
1593     TRACE("(%p) : w(%d) h(%d) fmt(%d) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, Lockable, *ppSurface, object->allocatedMemory, object->myDesc.Size);
1594     return D3D_OK;
1595 }
1596 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
1597     IDirect3DSurface8Impl *object;
1598
1599     ICOM_THIS(IDirect3DDevice8Impl,iface);
1600
1601     object  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1602     if (NULL == object) {
1603       *ppSurface = NULL;
1604       return D3DERR_OUTOFVIDEOMEMORY;
1605     }
1606     *ppSurface = (LPDIRECT3DSURFACE8) object;
1607     object->lpVtbl = &Direct3DSurface8_Vtbl;
1608     object->Device = This;
1609     /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1610     object->ResourceType = D3DRTYPE_SURFACE;
1611     object->Container = (IUnknown*) This;
1612     /*IUnknown_AddRef(object->Container);*/
1613
1614     object->ref = 1;
1615     object->myDesc.Width  = Width;
1616     object->myDesc.Height = Height;
1617     object->myDesc.Format = Format;
1618     object->myDesc.Type = D3DRTYPE_SURFACE;
1619     object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
1620     object->myDesc.Pool = D3DPOOL_DEFAULT;
1621     object->myDesc.MultiSampleType = MultiSample;
1622     object->bytesPerPixel = bytesPerPixel(Format);
1623     object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1624     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1625     object->lockable = TRUE;
1626     object->locked = FALSE;
1627
1628     TRACE("(%p) : w(%d) h(%d) fmt(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, *ppSurface, object->allocatedMemory, object->myDesc.Size);
1629     return D3D_OK;
1630 }
1631 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
1632     IDirect3DSurface8Impl *object;
1633
1634     ICOM_THIS(IDirect3DDevice8Impl,iface);
1635
1636     object  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1637     *ppSurface = (LPDIRECT3DSURFACE8) object;
1638     object->lpVtbl = &Direct3DSurface8_Vtbl;
1639     object->Device = This;
1640     /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1641     object->ResourceType = D3DRTYPE_SURFACE;
1642     object->Container = (IUnknown*) This;
1643     /*IUnknown_AddRef(object->Container);*/
1644
1645     object->ref = 1;
1646     object->myDesc.Width  = Width;
1647     object->myDesc.Height = Height;
1648     object->myDesc.Format = Format;
1649     object->myDesc.Type = D3DRTYPE_SURFACE;
1650     object->myDesc.Usage = 0;
1651     object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
1652     object->bytesPerPixel = bytesPerPixel(Format);
1653     object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1654     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1655     object->lockable = TRUE;
1656     object->locked = FALSE;
1657
1658     TRACE("(%p) : w(%d) h(%d) fmt(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, *ppSurface, object->allocatedMemory, object->myDesc.Size);
1659     return D3D_OK;
1660 }
1661 HRESULT  WINAPI  IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pSourceSurface,CONST RECT* pSourceRectsArray,UINT cRects,
1662                                                 IDirect3DSurface8* pDestinationSurface,CONST POINT* pDestPointsArray) {
1663
1664     HRESULT rc      = D3D_OK;
1665     IDirect3DBaseTexture8* texture = NULL;
1666
1667
1668     IDirect3DSurface8Impl *src = (IDirect3DSurface8Impl*) pSourceSurface;
1669     IDirect3DSurface8Impl *dst = (IDirect3DSurface8Impl*) pDestinationSurface;
1670
1671     ICOM_THIS(IDirect3DDevice8Impl,iface);
1672     TRACE("(%p) srcsur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
1673           pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
1674
1675     /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1676          a sample and doesnt seem to break anything as far as I can tell               */
1677     if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1678         TRACE("Formats do not match %x / %x\n", src->myDesc.Format, dst->myDesc.Format);
1679         rc = D3DERR_INVALIDCALL;
1680
1681     } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1682         TRACE("Converting dest to same format as source, since dest was unknown\n");
1683         dst->myDesc.Format = src->myDesc.Format;
1684
1685         /* Convert container as well */
1686         IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1687         if (texture != NULL) {
1688
1689             switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) texture)) {
1690             case D3DRTYPE_TEXTURE:
1691                 ((IDirect3DTexture8Impl *)texture)->format = src->myDesc.Format;
1692                 break;
1693             case D3DRTYPE_VOLUMETEXTURE:
1694                 ((IDirect3DVolumeTexture8Impl *)texture)->format = src->myDesc.Format;
1695                 break;
1696             case D3DRTYPE_CUBETEXTURE:
1697                 ((IDirect3DCubeTexture8Impl *)texture)->format = src->myDesc.Format;
1698                 break;
1699             default:
1700                 FIXME("Unhandled texture type\n");
1701             }
1702
1703             /** Releasing texture after GetContainer */
1704             IDirect3DBaseTexture8_Release(texture);   
1705         }
1706     }
1707
1708     /* Quick if complete copy ... */
1709     if (rc == D3D_OK && (cRects == 0 && pSourceRectsArray==NULL && pDestPointsArray==NULL &&
1710                          src->myDesc.Width == dst->myDesc.Width &&
1711                          src->myDesc.Height == dst->myDesc.Height)) {
1712         D3DLOCKED_RECT lr;
1713
1714         IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8)src, &lr, NULL, D3DLOCK_READONLY);
1715         IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8)dst, &lr, NULL, D3DLOCK_DISCARD);
1716         TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1717
1718         memcpy(dst->allocatedMemory, src->allocatedMemory, src->myDesc.Size);
1719
1720         IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8)src);
1721         IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8)dst);
1722         TRACE("Unlocked src and dst\n");
1723
1724     } else {
1725         int i;
1726         int bytesPerPixel = ((IDirect3DSurface8Impl *)pSourceSurface)->bytesPerPixel;
1727         int pitchFrom     = ((IDirect3DSurface8Impl *)pSourceSurface)->myDesc.Width * bytesPerPixel;
1728         int pitchTo       = ((IDirect3DSurface8Impl *)pDestinationSurface)->myDesc.Width * bytesPerPixel;
1729
1730         char *copyfrom = ((IDirect3DSurface8Impl *)pSourceSurface)->allocatedMemory;
1731         char *copyto   = ((IDirect3DSurface8Impl *)pDestinationSurface)->allocatedMemory;
1732
1733         /* Copy rect by rect */
1734         for (i=0; i<cRects; i++) {
1735             CONST RECT *r = &pSourceRectsArray[i];
1736             CONST POINT *p = &pDestPointsArray[i];
1737             char *from;
1738             char *to;
1739             int   copyperline   = (r->right - r->left) * bytesPerPixel;
1740             int j;
1741             D3DLOCKED_RECT lr;
1742             RECT           dest_rect;
1743
1744             TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top,
1745                   r->right, r->bottom, p->x, p->y);
1746
1747             IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8)src, &lr, r, D3DLOCK_READONLY);
1748             dest_rect.left = p->x;
1749             dest_rect.top = p->y;
1750             dest_rect.right = p->x + (r->right - r->left);
1751             dest_rect.left = p->y + (r->bottom - r->top);
1752             IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8)dst, &lr, &dest_rect, 0L);
1753             TRACE("Locked src and dst\n");
1754
1755             /* Find where to start */
1756             from = copyfrom + (r->top * pitchFrom) + (r->left * bytesPerPixel);
1757             to   = copyto   + (p->y * pitchTo) + (p->x * bytesPerPixel);
1758
1759             /* Copy line by line */
1760             for (j=0; j<(r->bottom - r->top); j++) {
1761                memcpy(to + (j*pitchTo), from + (j*pitchFrom), copyperline);
1762             }
1763
1764             IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8)src);
1765             IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8)dst);
1766             TRACE("Unlocked src and dst\n");
1767         }
1768     }
1769
1770     /* Set dirty */
1771     if (rc == D3D_OK) {
1772         IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1773         if (texture != NULL) {
1774
1775             switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) texture)) {
1776             case D3DRTYPE_TEXTURE:
1777                 {
1778                     IDirect3DTexture8Impl *pTexture = (IDirect3DTexture8Impl *)texture;
1779                     pTexture->Dirty = TRUE;
1780                 }
1781                 break;
1782             case D3DRTYPE_VOLUMETEXTURE:
1783                 {
1784                     IDirect3DVolumeTexture8Impl *pTexture = (IDirect3DVolumeTexture8Impl *)texture;
1785                     pTexture->Dirty = TRUE;
1786                 }
1787                 break;
1788             case D3DRTYPE_CUBETEXTURE:
1789                 {
1790                     IDirect3DCubeTexture8Impl *pTexture = (IDirect3DCubeTexture8Impl *)texture;
1791                     pTexture->Dirty = TRUE;
1792                 }
1793                 break;
1794             default:
1795                 FIXME("Unhandled texture type\n");
1796             }
1797
1798             /** Releasing texture after GetContainer */
1799             IDirect3DBaseTexture8_Release(texture);
1800         }
1801     }
1802
1803     return D3D_OK;
1804 }
1805 HRESULT  WINAPI  IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1806     ICOM_THIS(IDirect3DDevice8Impl,iface);
1807     FIXME("(%p) : stub\n", This);
1808     return D3D_OK;
1809 }
1810 HRESULT  WINAPI  IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1811     HRESULT hr;
1812     D3DLOCKED_RECT lockedRect;
1813     GLint  prev_store;
1814     GLenum prev_read;
1815
1816     ICOM_THIS(IDirect3DDevice8Impl,iface);
1817
1818     FIXME("(%p) : stub\n", This);
1819
1820     if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1821       return D3DERR_INVALIDCALL;
1822     }
1823
1824     hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, NULL, 0);
1825     if (FAILED(hr)) {
1826       return D3DERR_INVALIDCALL;
1827     }
1828
1829     ENTER_GL();
1830
1831     glFlush();
1832     vcheckGLcall("glFlush");
1833     glGetIntegerv(GL_READ_BUFFER, &prev_read);
1834     vcheckGLcall("glIntegerv");
1835     glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1836     vcheckGLcall("glIntegerv");
1837  
1838     glReadBuffer(GL_FRONT);
1839     vcheckGLcall("glReadBuffer");
1840     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1841     vcheckGLcall("glPixelStorei");
1842     glReadPixels(0, 0, This->PresentParms.BackBufferWidth, This->PresentParms.BackBufferHeight,
1843                  GL_BGRA, GL_UNSIGNED_BYTE, lockedRect.pBits);
1844     vcheckGLcall("glReadPixels");
1845     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1846     vcheckGLcall("glPixelStorei");
1847     glReadBuffer(prev_read);
1848     vcheckGLcall("glReadBuffer");
1849     LEAVE_GL();
1850
1851     hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1852     return hr;
1853 }
1854 HRESULT  WINAPI  IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1855     ICOM_THIS(IDirect3DDevice8Impl,iface);
1856
1857     if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1858       TRACE("Trying to do a NOP SetRenderTarget operation\n");
1859       return D3D_OK;
1860     }
1861     
1862     FIXME("(%p) : invalid stub expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1863
1864     return D3D_OK;
1865 }
1866 HRESULT  WINAPI  IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1867     ICOM_THIS(IDirect3DDevice8Impl,iface);
1868
1869     TRACE("(%p)->(%p)\n", This, This->frontBuffer);
1870     
1871     *ppRenderTarget = (LPDIRECT3DSURFACE8) This->frontBuffer;
1872     IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1873     
1874     return D3D_OK;
1875 }
1876 HRESULT  WINAPI  IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1877     ICOM_THIS(IDirect3DDevice8Impl,iface);
1878
1879     TRACE("(%p)->(%p)\n", This, ppZStencilSurface);
1880     
1881     /* Note inc ref on returned surface */
1882     *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->depthStencilBuffer;
1883     IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1884
1885     return D3D_OK;
1886 }
1887
1888 HRESULT  WINAPI  IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1889     ICOM_THIS(IDirect3DDevice8Impl,iface);
1890     TRACE("(%p) : stub\n", This);
1891     return D3D_OK;
1892 }
1893 HRESULT  WINAPI  IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1894     ICOM_THIS(IDirect3DDevice8Impl,iface);
1895     TRACE("(%p)\n", This);
1896
1897     ENTER_GL();
1898
1899     glFlush();
1900     checkGLcall("glFlush");
1901
1902     /* Useful for debugging sometimes!
1903     printf("Hit Enter ...\n");
1904     getchar(); */
1905
1906     LEAVE_GL();
1907     return D3D_OK;
1908 }
1909 HRESULT  WINAPI  IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil) {
1910     ICOM_THIS(IDirect3DDevice8Impl,iface);
1911
1912     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1913       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1914       when the depth-buffer format does not contain stencil buffer information, this method fails. */
1915     GLbitfield glMask = 0;
1916     GLboolean old_ztest;
1917     GLfloat old_z_clear_value;
1918     GLint   old_stencil_clear_value;
1919     GLfloat old_color_clear_value[4];
1920
1921     int i;
1922     CONST D3DRECT   *curRect;
1923
1924     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1925           Count, pRects, Flags, Z, Stencil);
1926
1927     ENTER_GL();
1928     if (Count > 0 && pRects) {
1929         glEnable(GL_SCISSOR_TEST);
1930         checkGLcall("glEnable GL_SCISSOR_TEST");
1931         curRect = pRects;
1932     } else {
1933         curRect = NULL;
1934     }
1935
1936     for (i = 0; i < Count || i == 0; i++) {
1937
1938         if (curRect) {
1939             /* Note gl uses lower left, width/height */
1940             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1941                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1942                   curRect->x1, curRect->y2, curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1943             glScissor(curRect->x1, curRect->y2, curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1944             checkGLcall("glScissor");
1945         }
1946
1947         /* Clear the whole screen */
1948         if (Flags & D3DCLEAR_STENCIL) { 
1949             glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1950             glClearStencil(Stencil);
1951             checkGLcall("glClearStencil");
1952             glMask = glMask | GL_STENCIL_BUFFER_BIT;
1953         }
1954
1955         if (Flags & D3DCLEAR_ZBUFFER) {
1956             glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1957             glDepthMask(GL_TRUE); 
1958             glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1959             glClearDepth(Z);
1960             checkGLcall("glClearDepth");
1961             glMask = glMask | GL_DEPTH_BUFFER_BIT;
1962         }
1963
1964         if (Flags & D3DCLEAR_TARGET) {
1965             TRACE("Clearing screen with glClear to color %lx\n", Color);
1966             glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1967             glClearColor(((Color >> 16) & 0xFF) / 255.0, 
1968                          ((Color >>  8) & 0xFF) / 255.0,
1969                          ((Color >>  0) & 0xFF) / 255.0, 
1970                          ((Color >> 24) & 0xFF) / 255.0);
1971             checkGLcall("glClearColor");
1972             glMask = glMask | GL_COLOR_BUFFER_BIT;
1973         }
1974
1975         glClear(glMask);
1976         checkGLcall("glClear");
1977
1978         if (Flags & D3DCLEAR_STENCIL) {
1979           glClearStencil(old_stencil_clear_value);
1980         }    
1981         if (Flags & D3DCLEAR_ZBUFFER) {
1982           glDepthMask(old_ztest);
1983           glClearDepth(old_z_clear_value);
1984         }
1985         if (Flags & D3DCLEAR_TARGET) {
1986           glClearColor(old_color_clear_value[0], 
1987                        old_color_clear_value[1],
1988                        old_color_clear_value[2], 
1989                        old_color_clear_value[3]);
1990         }
1991
1992         if (curRect) curRect = curRect + sizeof(D3DRECT);
1993     }
1994
1995     if (Count > 0 && pRects) {
1996         glDisable(GL_SCISSOR_TEST);
1997         checkGLcall("glDisable");
1998     }
1999     LEAVE_GL();
2000
2001     return D3D_OK;
2002 }
2003 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts,CONST D3DMATRIX* lpmatrix) {
2004     ICOM_THIS(IDirect3DDevice8Impl,iface);
2005     D3DMATRIX m;
2006     int k;
2007     float f;
2008     BOOL viewChanged = TRUE;
2009     int  Stage;
2010
2011     /* Most of this routine, comments included copied from ddraw tree initially: */
2012     TRACE("(%p) : State=%d\n", This, d3dts);
2013
2014     This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
2015     This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
2016     memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2017
2018     /* Handle recording of state blocks */
2019     if (This->isRecordingState) {
2020         TRACE("Recording... not performing anything\n");
2021         return D3D_OK;
2022     }
2023
2024     /*
2025        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2026
2027        where ViewMat = Camera space, WorldMat = world space.
2028
2029        In OpenGL, camera and world space is combined into GL_MODELVIEW
2030        matrix.  The Projection matrix stay projection matrix. */
2031
2032     /* After reading through both OpenGL and Direct3D documentations, I
2033        thought that D3D matrices were written in 'line major mode' transposed
2034        from OpenGL's 'column major mode'. But I found out that a simple memcpy
2035        works fine to transfer one matrix format to the other (it did not work
2036        when transposing)....
2037
2038        So :
2039         1) are the documentations wrong
2040         2) does the matrix work even if they are not read correctly
2041         3) is Mesa's implementation of OpenGL not compliant regarding Matrix
2042            loading using glLoadMatrix ?
2043
2044        Anyway, I always use 'conv_mat' to transfer the matrices from one format
2045        to the other so that if I ever find out that I need to transpose them, I
2046        will able to do it quickly, only by changing the macro conv_mat. */
2047
2048     if (d3dts <= 256) { /* WORLDMATRIX(0) == 256! */
2049       switch (d3dts) {
2050       case D3DTS_WORLDMATRIX(0):
2051         conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)]);
2052         break;
2053
2054       case D3DTS_VIEW:
2055         conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_VIEW]);
2056         break;
2057
2058       case D3DTS_PROJECTION:
2059         conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_PROJECTION]);
2060         break;
2061
2062       case D3DTS_TEXTURE0:
2063       case D3DTS_TEXTURE1:
2064       case D3DTS_TEXTURE2:
2065       case D3DTS_TEXTURE3:
2066       case D3DTS_TEXTURE4:
2067       case D3DTS_TEXTURE5:
2068       case D3DTS_TEXTURE6:
2069       case D3DTS_TEXTURE7:
2070         conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
2071         break;
2072
2073       default:
2074         FIXME("Unhandled transform state!!\n");
2075         break;
2076       }
2077     } else {
2078       /** 
2079        * Indexed Vertex Blending Matrices 256 -> 511 
2080        */
2081       /** store it */
2082       conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
2083       if (checkGLSupport(ARB_VERTEX_BLEND)) {
2084           FIXME("TODO\n");
2085       } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
2086           FIXME("TODO\n");
2087       }
2088     }
2089
2090     /*
2091      * Move the GL operation to outside of switch to make it work
2092      * regardless of transform set order.
2093      */
2094     ENTER_GL();
2095     if (memcmp(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX))) {
2096         glMatrixMode(GL_PROJECTION);
2097         checkGLcall("glMatrixMode");
2098         glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
2099         checkGLcall("glLoadMatrixf");
2100         memcpy(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX));
2101     } else {
2102         TRACE("Skipping as projection already correct\n");
2103     }
2104
2105     glMatrixMode(GL_MODELVIEW);
2106     checkGLcall("glMatrixMode");
2107     viewChanged = FALSE;
2108     if (memcmp(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX))) {
2109        glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2110        checkGLcall("glLoadMatrixf");
2111        memcpy(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX));
2112        viewChanged = TRUE;
2113
2114        /* If we are changing the View matrix, reset the light and clipping planes to the new view */
2115        if (d3dts == D3DTS_VIEW) {
2116
2117            /* NOTE: We have to reset the positions even if the light/plane is not currently
2118               enabled, since the call to enable it will not reset the position.             */
2119
2120            /* Reset lights */
2121            for (k = 0; k < This->maxLights; k++) {
2122                glLightfv(GL_LIGHT0 + k, GL_POSITION,       &This->lightPosn[k][0]);
2123                checkGLcall("glLightfv posn");
2124                glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
2125                checkGLcall("glLightfv dirn");
2126            }
2127
2128            /* Reset Clipping Planes if clipping is enabled */
2129            for (k = 0; k < This->clipPlanes; k++) {
2130                glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
2131                checkGLcall("glClipPlane");
2132            }
2133
2134            /* Reapply texture transforms as based off modelview when applied */
2135            for (Stage = 0; Stage < This->TextureUnits; Stage++) {
2136
2137                /* Now apply texture transforms if not applying to the dummy textures */
2138 #if defined(GL_VERSION_1_3)
2139                glActiveTexture(GL_TEXTURE0 + Stage);
2140 #else 
2141                glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2142 #endif
2143                checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage);");
2144
2145                glMatrixMode(GL_TEXTURE);
2146                if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2147                   glLoadIdentity();
2148                } else {
2149                   D3DMATRIX fred;
2150                   conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2151                   glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2152                }
2153                checkGLcall("Load matrix for texture");
2154            }
2155            glMatrixMode(GL_MODELVIEW);  /* Always leave in model view */
2156        }
2157     } else if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) {
2158         /* Now apply texture transforms if not applying to the dummy textures */
2159         Stage = d3dts-D3DTS_TEXTURE0;
2160
2161         if (memcmp(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0], sizeof(D3DMATRIX))) {
2162            memcpy(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0], sizeof(D3DMATRIX));
2163
2164 #if defined(GL_VERSION_1_3)
2165            glActiveTexture(GL_TEXTURE0 + Stage);
2166 #else
2167            glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2168 #endif
2169            checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage)");
2170
2171            glMatrixMode(GL_TEXTURE);
2172            if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2173               glLoadIdentity();
2174            } else {
2175               D3DMATRIX fred;
2176               conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2177               glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2178            }
2179            checkGLcall("Load matrix for texture");
2180            glMatrixMode(GL_MODELVIEW);  /* Always leave in model view */
2181         } else {
2182             TRACE("Skipping texture transform as already correct\n");
2183         }
2184
2185     } else {
2186         TRACE("Skipping view setup as view already correct\n");
2187     }
2188
2189     /**
2190      * Vertex Blending as described
2191      *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/enums/d3dvertexblendflags.asp
2192      */
2193     switch (This->UpdateStateBlock->vertex_blend) {
2194     case D3DVBF_DISABLE:
2195       {
2196           if (viewChanged == TRUE || 
2197               (memcmp(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX)))) {
2198                memcpy(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX));
2199               if (viewChanged==FALSE) {
2200                  glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2201                  checkGLcall("glLoadMatrixf");
2202               }
2203               glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
2204               checkGLcall("glMultMatrixf");
2205           } else {
2206               TRACE("Skipping as world already correct\n");
2207           }
2208       }
2209       break;
2210     case D3DVBF_1WEIGHTS:
2211     case D3DVBF_2WEIGHTS:
2212     case D3DVBF_3WEIGHTS:
2213       {
2214           FIXME("valid/correct D3DVBF_[1..3]WEIGHTS\n");
2215           /*
2216            * doc seems to say that the weight values must be in vertex data (specified in FVF by D3DFVF_XYZB*)
2217            * so waiting for the values before matrix work
2218           for (k = 0; k < This->UpdateStateBlock->vertex_blend; ++k) {
2219             glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(k)].u.m[0][0]);
2220             checkGLcall("glMultMatrixf");
2221           }
2222           */
2223       }
2224       break;
2225     case D3DVBF_TWEENING:
2226       {
2227           FIXME("valid/correct D3DVBF_TWEENING\n");
2228           f = This->UpdateStateBlock->tween_factor;
2229           m.u.s._11 = f; m.u.s._12 = f; m.u.s._13 = f; m.u.s._14 = f;
2230           m.u.s._21 = f; m.u.s._22 = f; m.u.s._23 = f; m.u.s._24 = f;
2231           m.u.s._31 = f; m.u.s._32 = f; m.u.s._33 = f; m.u.s._34 = f;
2232           m.u.s._41 = f; m.u.s._42 = f; m.u.s._43 = f; m.u.s._44 = f;
2233           if (viewChanged==FALSE) {
2234               glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2235               checkGLcall("glLoadMatrixf");
2236           }
2237           glMultMatrixf((float *) &m.u.m[0][0]);
2238           checkGLcall("glMultMatrixf");
2239       }
2240       break;
2241     case D3DVBF_0WEIGHTS:
2242       {
2243           FIXME("valid/correct D3DVBF_0WEIGHTS\n");
2244           /* single matrix of weight 1.0f */
2245           m.u.s._11 = 1.0f; m.u.s._12 = 1.0f; m.u.s._13 = 1.0f; m.u.s._14 = 1.0f;
2246           m.u.s._21 = 1.0f; m.u.s._22 = 1.0f; m.u.s._23 = 1.0f; m.u.s._24 = 1.0f;
2247           m.u.s._31 = 1.0f; m.u.s._32 = 1.0f; m.u.s._33 = 1.0f; m.u.s._34 = 1.0f;
2248           m.u.s._41 = 1.0f; m.u.s._42 = 1.0f; m.u.s._43 = 1.0f; m.u.s._44 = 1.0f;
2249           if (viewChanged == FALSE) {
2250               glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2251               checkGLcall("glLoadMatrixf");
2252           }
2253           glMultMatrixf((float *) &m.u.m[0][0]);
2254           checkGLcall("glMultMatrixf");
2255       }
2256       break;
2257     default:
2258       break; /* stupid compilator */
2259     }
2260
2261     LEAVE_GL();
2262
2263     return D3D_OK;
2264
2265 }
2266 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
2267     ICOM_THIS(IDirect3DDevice8Impl,iface);
2268     TRACE("(%p) : for State %d\n", This, State);
2269     memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
2270     return D3D_OK;
2271 }
2272
2273 HRESULT  WINAPI  IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2274     D3DMATRIX *mat = NULL;
2275     D3DMATRIX temp;
2276
2277     /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
2278         but works regardless of recording being on. 
2279         If this is found to be wrong, change to StateBlock.                             */
2280     ICOM_THIS(IDirect3DDevice8Impl,iface);
2281     TRACE("(%p) : For state %u\n", This, State);
2282
2283     if (State < HIGHEST_TRANSFORMSTATE)
2284     {
2285         mat = &This->UpdateStateBlock->transforms[State];
2286     } else {
2287         FIXME("Unhandled transform state!!\n");
2288     }
2289
2290     /* Copied from ddraw code:  */
2291     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);
2292     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);
2293     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);
2294     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);
2295
2296     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);
2297     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);
2298     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);
2299     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);
2300
2301     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);
2302     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);
2303     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);
2304     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);
2305
2306     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);
2307     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);
2308     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);
2309     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);
2310
2311     /* Apply change via set transform - will reapply to eg. lights this way */
2312     IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
2313     return D3D_OK;
2314 }
2315 HRESULT  WINAPI  IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
2316     ICOM_THIS(IDirect3DDevice8Impl,iface);
2317
2318     TRACE("(%p)\n", This);
2319     This->UpdateStateBlock->Changed.viewport = TRUE;
2320     This->UpdateStateBlock->Set.viewport = TRUE;
2321     memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
2322
2323     /* Handle recording of state blocks */
2324     if (This->isRecordingState) {
2325         TRACE("Recording... not performing anything\n");
2326         return D3D_OK;
2327     }
2328
2329     TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2330           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2331
2332     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2333     checkGLcall("glDepthRange");
2334     /* Note: GL requires lower left, DirectX supplies upper left */
2335     glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)), 
2336                pViewport->Width, pViewport->Height);
2337     checkGLcall("glViewport");
2338
2339
2340     return D3D_OK;
2341
2342 }
2343 HRESULT  WINAPI  IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
2344     ICOM_THIS(IDirect3DDevice8Impl,iface);
2345     TRACE("(%p)\n", This);
2346     memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
2347     return D3D_OK;
2348 }
2349
2350 HRESULT  WINAPI  IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
2351     ICOM_THIS(IDirect3DDevice8Impl,iface);
2352
2353     This->UpdateStateBlock->Changed.material = TRUE;
2354     This->UpdateStateBlock->Set.material = TRUE;
2355     memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
2356
2357     /* Handle recording of state blocks */
2358     if (This->isRecordingState) {
2359         TRACE("Recording... not performing anything\n");
2360         return D3D_OK;
2361     }
2362
2363     ENTER_GL();
2364     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2365     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2366     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2367     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2368     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2369
2370     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&This->UpdateStateBlock->material.Ambient);
2371     checkGLcall("glMaterialfv");
2372     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&This->UpdateStateBlock->material.Diffuse);
2373     checkGLcall("glMaterialfv");
2374
2375     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&This->UpdateStateBlock->material.Specular);
2376     checkGLcall("glMaterialfv");
2377     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&This->UpdateStateBlock->material.Emissive);
2378     checkGLcall("glMaterialfv");
2379     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
2380     checkGLcall("glMaterialf");
2381
2382     LEAVE_GL();
2383     return D3D_OK;
2384 }
2385 HRESULT  WINAPI  IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
2386     ICOM_THIS(IDirect3DDevice8Impl,iface);
2387     memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
2388     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2389     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2390     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2391     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2392     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2393     return D3D_OK;
2394 }
2395
2396 HRESULT  WINAPI  IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST D3DLIGHT8* pLight) {
2397     float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
2398     float rho;
2399     float quad_att;
2400
2401     ICOM_THIS(IDirect3DDevice8Impl,iface);
2402     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2403
2404     if (Index > This->maxLights) {
2405         FIXME("Cannot handle more lights than device supports\n");
2406         return D3DERR_INVALIDCALL;
2407     }
2408
2409     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,
2410           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2411           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2412           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2413     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2414           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2415     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2416
2417     This->UpdateStateBlock->Changed.lights[Index] = TRUE;
2418     This->UpdateStateBlock->Set.lights[Index] = TRUE;
2419     memcpy(&This->UpdateStateBlock->lights[Index], pLight, sizeof(D3DLIGHT8));
2420
2421     /* Handle recording of state blocks */
2422     if (This->isRecordingState) {
2423         TRACE("Recording... not performing anything\n");
2424         return D3D_OK;
2425     }
2426
2427     /* Diffuse: */
2428     colRGBA[0] = pLight->Diffuse.r;
2429     colRGBA[1] = pLight->Diffuse.g;
2430     colRGBA[2] = pLight->Diffuse.b;
2431     colRGBA[3] = pLight->Diffuse.a;
2432     glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
2433     checkGLcall("glLightfv");
2434
2435     /* Specular */
2436     colRGBA[0] = pLight->Specular.r;
2437     colRGBA[1] = pLight->Specular.g;
2438     colRGBA[2] = pLight->Specular.b;
2439     colRGBA[3] = pLight->Specular.a;
2440     glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
2441     checkGLcall("glLightfv");
2442
2443     /* Ambient */
2444     colRGBA[0] = pLight->Ambient.r;
2445     colRGBA[1] = pLight->Ambient.g;
2446     colRGBA[2] = pLight->Ambient.b;
2447     colRGBA[3] = pLight->Ambient.a;
2448     glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
2449     checkGLcall("glLightfv");
2450
2451     /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
2452     glMatrixMode(GL_MODELVIEW);
2453     glPushMatrix();
2454     glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2455
2456     /* Attenuation - Are these right? guessing... */
2457     glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  pLight->Attenuation0);
2458     checkGLcall("glLightf");
2459     glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    pLight->Attenuation1);
2460     checkGLcall("glLightf");
2461
2462     quad_att = 1.4/(pLight->Range*pLight->Range);
2463     if (quad_att < pLight->Attenuation2) quad_att = pLight->Attenuation2;
2464     glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
2465     checkGLcall("glLightf");
2466
2467     switch (pLight->Type) {
2468     case D3DLIGHT_POINT:
2469         /* Position */
2470         This->lightPosn[Index][0] = pLight->Position.x;
2471         This->lightPosn[Index][1] = pLight->Position.y;
2472         This->lightPosn[Index][2] = pLight->Position.z;
2473         This->lightPosn[Index][3] = 1.0;
2474         glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2475         checkGLcall("glLightfv");
2476
2477         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
2478         checkGLcall("glLightf");
2479
2480         /* FIXME: Range */
2481         break;
2482
2483     case D3DLIGHT_SPOT:
2484         /* Position */
2485         This->lightPosn[Index][0] = pLight->Position.x;
2486         This->lightPosn[Index][1] = pLight->Position.y;
2487         This->lightPosn[Index][2] = pLight->Position.z;
2488         This->lightPosn[Index][3] = 1.0;
2489         glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2490         checkGLcall("glLightfv");
2491
2492         /* Direction */
2493         This->lightDirn[Index][0] = pLight->Direction.x;
2494         This->lightDirn[Index][1] = pLight->Direction.y;
2495         This->lightDirn[Index][2] = pLight->Direction.z;
2496         This->lightDirn[Index][3] = 1.0;
2497         glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
2498         checkGLcall("glLightfv");
2499
2500         /*
2501          * opengl-ish and d3d-ish spot lights use too different models for the
2502          * light "intensity" as a function of the angle towards the main light direction,
2503          * so we only can approximate very roughly.
2504          * however spot lights are rather rarely used in games (if ever used at all).
2505          * furthermore if still used, probably nobody pays attention to such details.
2506          */
2507         if (pLight->Falloff == 0) {
2508             rho = 6.28f;
2509         } else {
2510             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2511         }
2512         if (rho < 0.0001) rho = 0.0001f;
2513         glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, -0.3/log(cos(rho/2)));
2514         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, pLight->Phi*90/M_PI);
2515
2516         /* FIXME: Range */
2517         break;
2518     case D3DLIGHT_DIRECTIONAL:
2519         /* Direction */
2520         This->lightPosn[Index][0] = -pLight->Direction.x;
2521         This->lightPosn[Index][1] = -pLight->Direction.y;
2522         This->lightPosn[Index][2] = -pLight->Direction.z;
2523         This->lightPosn[Index][3] = 0.0;
2524         glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
2525         checkGLcall("glLightfv");
2526
2527         glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
2528         glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
2529
2530
2531         break;
2532     default:
2533         FIXME("Unrecognized light type %d\n", pLight->Type);
2534     }
2535
2536     /* Restore the modelview matrix */
2537     glPopMatrix();
2538
2539     return D3D_OK;
2540 }
2541 HRESULT  WINAPI  IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
2542     ICOM_THIS(IDirect3DDevice8Impl,iface);
2543     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2544     
2545     if (Index > This->maxLights) {
2546         FIXME("Cannot handle more lights than device supports\n");
2547         return D3DERR_INVALIDCALL;
2548     }
2549
2550     memcpy(pLight, &This->StateBlock->lights[Index], sizeof(D3DLIGHT8));
2551     return D3D_OK;
2552 }
2553 HRESULT  WINAPI  IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
2554     ICOM_THIS(IDirect3DDevice8Impl,iface);
2555     TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2556
2557     if (Index > This->maxLights) {
2558         FIXME("Cannot handle more lights than device supports\n");
2559         return D3DERR_INVALIDCALL;
2560     }
2561
2562     This->UpdateStateBlock->Changed.lightEnable[Index] = TRUE;
2563     This->UpdateStateBlock->Set.lightEnable[Index] = TRUE;
2564     This->UpdateStateBlock->lightEnable[Index] = Enable;
2565
2566     /* Handle recording of state blocks */
2567     if (This->isRecordingState) {
2568         TRACE("Recording... not performing anything\n");
2569         return D3D_OK;
2570     }
2571
2572     if (Enable) {
2573         glEnable(GL_LIGHT0+Index);
2574         checkGLcall("glEnable GL_LIGHT0+Index");
2575     } else {
2576         glDisable(GL_LIGHT0+Index);
2577         checkGLcall("glDisable GL_LIGHT0+Index");
2578     }
2579     return D3D_OK;
2580 }
2581 HRESULT  WINAPI  IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2582     ICOM_THIS(IDirect3DDevice8Impl,iface);
2583     TRACE("(%p) : for idx(%ld)\n", This, Index);
2584
2585     if (Index > This->maxLights) {
2586         FIXME("Cannot handle more lights than device supports\n");
2587         return D3DERR_INVALIDCALL;
2588     }
2589
2590     *pEnable = This->StateBlock->lightEnable[Index];
2591     return D3D_OK;
2592 }
2593 HRESULT  WINAPI  IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2594     ICOM_THIS(IDirect3DDevice8Impl,iface);
2595     TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2596
2597     /* Validate Index */
2598     if (Index >= This->clipPlanes ) {
2599         TRACE("Application has requested clipplane this device doesnt support\n");
2600         return D3DERR_INVALIDCALL;
2601     }
2602
2603     This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2604     This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2605     This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2606     This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2607     This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2608     This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2609
2610     /* Handle recording of state blocks */
2611     if (This->isRecordingState) {
2612         TRACE("Recording... not performing anything\n");
2613         return D3D_OK;
2614     }
2615
2616     /* Apply it */
2617
2618     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2619     glMatrixMode(GL_MODELVIEW);
2620     glPushMatrix();
2621     glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2622
2623     TRACE("Clipplane [%f,%f,%f,%f]\n", This->UpdateStateBlock->clipplane[Index][0], This->UpdateStateBlock->clipplane[Index][1],
2624           This->UpdateStateBlock->clipplane[Index][2], This->UpdateStateBlock->clipplane[Index][3]);
2625     glClipPlane(GL_CLIP_PLANE0+Index, This->UpdateStateBlock->clipplane[Index]);
2626
2627     glPopMatrix();
2628     checkGLcall("glClipPlane");
2629
2630     return D3D_OK;
2631 }
2632 HRESULT  WINAPI  IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2633     ICOM_THIS(IDirect3DDevice8Impl,iface);
2634     TRACE("(%p) : for idx %ld\n", This, Index);
2635
2636     /* Validate Index */
2637     if (Index >= This->clipPlanes ) {
2638         TRACE("Application has requested clipplane this device doesnt support\n");
2639         return D3DERR_INVALIDCALL;
2640     }
2641
2642     pPlane[0] = This->StateBlock->clipplane[Index][0];
2643     pPlane[1] = This->StateBlock->clipplane[Index][0];
2644     pPlane[2] = This->StateBlock->clipplane[Index][0];
2645     pPlane[3] = This->StateBlock->clipplane[Index][0];
2646     return D3D_OK;
2647 }
2648 HRESULT  WINAPI  IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2649     ICOM_THIS(IDirect3DDevice8Impl,iface);
2650     DWORD OldValue = This->StateBlock->renderstate[State];
2651         
2652     TRACE("(%p)->state = %d, value = %ld\n", This, State, Value);
2653     This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2654     This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2655     This->UpdateStateBlock->renderstate[State] = Value;
2656
2657     /* Handle recording of state blocks */
2658     if (This->isRecordingState) {
2659         TRACE("Recording... not performing anything\n");
2660         return D3D_OK;
2661     }
2662
2663     switch (State) {
2664     case D3DRS_FILLMODE                  :
2665         switch ((D3DFILLMODE) Value) {
2666         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2667         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2668         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2669         default:
2670             FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2671         }
2672         checkGLcall("glPolygonMode (fillmode)");
2673         break;
2674
2675     case D3DRS_LIGHTING                  :
2676         if (Value) {
2677             glEnable(GL_LIGHTING);
2678             checkGLcall("glEnable GL_LIGHTING");
2679         } else {
2680             glDisable(GL_LIGHTING);
2681             checkGLcall("glDisable GL_LIGHTING");
2682         }
2683         break;
2684
2685     case D3DRS_ZENABLE                   :
2686         switch ((D3DZBUFFERTYPE) Value) {
2687         case D3DZB_FALSE:
2688             glDisable(GL_DEPTH_TEST);
2689             checkGLcall("glDisable GL_DEPTH_TEST");
2690             break;
2691         case D3DZB_TRUE:
2692             glEnable(GL_DEPTH_TEST);
2693             checkGLcall("glEnable GL_DEPTH_TEST");
2694             break;
2695
2696         case D3DZB_USEW:
2697         default:
2698             FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2699         }
2700         break;
2701
2702     case D3DRS_CULLMODE                  :
2703
2704         /* If we are culling "back faces with clockwise vertices" then
2705            set front faces to be counter clockwise and enable culling  
2706            of back faces                                               */
2707         switch ((D3DCULL) Value) {
2708         case D3DCULL_NONE:
2709             glDisable(GL_CULL_FACE);
2710             checkGLcall("glDisable GL_CULL_FACE");
2711             break;
2712         case D3DCULL_CW:
2713             glEnable(GL_CULL_FACE);
2714             checkGLcall("glEnable GL_CULL_FACE");
2715             glFrontFace(GL_CCW);
2716             checkGLcall("glFrontFace GL_CCW");
2717             glCullFace(GL_BACK);
2718             break;
2719         case D3DCULL_CCW:
2720             glEnable(GL_CULL_FACE);
2721             checkGLcall("glEnable GL_CULL_FACE");
2722             glFrontFace(GL_CW); 
2723             checkGLcall("glFrontFace GL_CW");
2724             glCullFace(GL_BACK);
2725             break;
2726         default:
2727             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2728         }
2729         break;
2730
2731     case D3DRS_SHADEMODE                 :
2732         switch ((D3DSHADEMODE) Value) {
2733         case D3DSHADE_FLAT:
2734             glShadeModel(GL_FLAT);
2735             checkGLcall("glShadeModel");
2736             break;
2737         case D3DSHADE_GOURAUD:
2738             glShadeModel(GL_SMOOTH);
2739             checkGLcall("glShadeModel");
2740             break;
2741         case D3DSHADE_PHONG:
2742             FIXME("D3DSHADE_PHONG isnt supported?\n");
2743             return D3DERR_INVALIDCALL;
2744         default:
2745             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2746         }
2747         break;
2748
2749     case D3DRS_DITHERENABLE              :
2750         if (Value) {
2751             glEnable(GL_DITHER);
2752             checkGLcall("glEnable GL_DITHER");
2753         } else {
2754             glDisable(GL_DITHER);
2755             checkGLcall("glDisable GL_DITHER");
2756         }
2757         break;
2758
2759     case D3DRS_ZWRITEENABLE              :
2760         if (Value) {
2761             glDepthMask(1);
2762             checkGLcall("glDepthMask");
2763         } else {
2764             glDepthMask(0);
2765             checkGLcall("glDepthMask");
2766         }
2767         break;
2768
2769     case D3DRS_ZFUNC                     :
2770         {
2771             int glParm = GL_LESS;
2772
2773             switch ((D3DCMPFUNC) Value) {
2774             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2775             case D3DCMP_LESS:          glParm=GL_LESS; break;
2776             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2777             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2778             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2779             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2780             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2781             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2782             default:
2783                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2784             }
2785             glDepthFunc(glParm);
2786             checkGLcall("glDepthFunc");
2787         }
2788         break;
2789
2790     case D3DRS_AMBIENT                   :
2791         {
2792
2793             float col[4];
2794             col[0] = ((Value >> 16) & 0xFF) / 255.0;
2795             col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2796             col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2797             col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2798             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0],col[1],col[2],col[3]);
2799             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2800             checkGLcall("glLightModel for MODEL_AMBIENT");
2801
2802         }
2803         break;
2804
2805     case D3DRS_ALPHABLENDENABLE          :
2806         if (Value) {
2807             glEnable(GL_BLEND);
2808             checkGLcall("glEnable GL_BLEND");
2809         } else {
2810             glDisable(GL_BLEND);
2811             checkGLcall("glDisable GL_BLEND");
2812         };
2813         break;
2814
2815     case D3DRS_SRCBLEND                  :
2816     case D3DRS_DESTBLEND                 :
2817         {
2818             int newVal = GL_ZERO;
2819             switch (Value) {
2820             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
2821             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
2822             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
2823             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
2824             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
2825             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
2826             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
2827             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
2828             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
2829             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
2830             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
2831
2832             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
2833                 This->srcBlend = newVal;
2834                 This->dstBlend = newVal;
2835                 break;
2836
2837             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
2838                 This->srcBlend = newVal;
2839                 This->dstBlend = newVal;
2840                 break;
2841             default:
2842                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2843             }
2844
2845             if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2846             if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2847             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2848             glBlendFunc(This->srcBlend, This->dstBlend);
2849
2850             checkGLcall("glBlendFunc");
2851         }
2852         break;
2853
2854     case D3DRS_ALPHATESTENABLE           :
2855         if (Value) {
2856             glEnable(GL_ALPHA_TEST);
2857             checkGLcall("glEnable GL_ALPHA_TEST");
2858         } else {
2859             glDisable(GL_ALPHA_TEST);
2860             checkGLcall("glDisable GL_ALPHA_TEST");
2861         }
2862         break;
2863
2864     case D3DRS_ALPHAFUNC                 :
2865         {
2866             int glParm = GL_LESS;
2867             float ref = 1.0;
2868
2869             glGetFloatv(GL_ALPHA_TEST_REF, &ref);
2870             checkGLcall("glGetFloatv(GL_ALPHA_TEST_REF, &ref);");
2871
2872             switch ((D3DCMPFUNC) Value) {
2873             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2874             case D3DCMP_LESS:          glParm=GL_LESS; break;
2875             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2876             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2877             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2878             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2879             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2880             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2881             default:
2882                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2883             }
2884             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2885             glAlphaFunc(glParm, ref);
2886             checkGLcall("glAlphaFunc");
2887         }
2888         break;
2889
2890     case D3DRS_ALPHAREF                  :
2891         {
2892             int glParm = GL_LESS;
2893             float ref = 1.0;
2894
2895             glGetIntegerv(GL_ALPHA_TEST_FUNC, &glParm);
2896             checkGLcall("glGetFloatv(GL_ALPHA_TEST_FUNC, &glParm);");
2897
2898             ref = ((float) Value) / 255.0;
2899             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2900             glAlphaFunc(glParm, ref);
2901             checkGLcall("glAlphaFunc");
2902         }
2903         break;
2904
2905     case D3DRS_CLIPPLANEENABLE           :
2906     case D3DRS_CLIPPING                  :
2907         {
2908             /* Ensure we only do the changed clip planes */
2909             DWORD enable  = 0xFFFFFFFF;
2910             DWORD disable = 0x00000000;
2911             
2912             /* If enabling / disabling all */
2913             if (State == D3DRS_CLIPPING) {
2914                 if (Value) {
2915                     enable  = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2916                     disable = 0x00;
2917                 } else {
2918                     disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2919                     enable  = 0x00;
2920                 }
2921             } else {
2922                 enable =   Value & ~OldValue;
2923                 disable = ~Value &  OldValue;
2924             }
2925             
2926             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
2927             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
2928             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
2929             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
2930             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
2931             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
2932             
2933             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2934             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2935             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2936             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2937             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2938             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2939         }
2940         break;
2941
2942     case D3DRS_BLENDOP                   :
2943         {
2944             int glParm = GL_FUNC_ADD;
2945
2946             switch ((D3DBLENDOP) Value) {
2947             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
2948             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
2949             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2950             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
2951             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
2952             default:
2953                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2954             }
2955             TRACE("glBlendEquation(%x)\n", glParm);
2956             glBlendEquation(glParm);
2957             checkGLcall("glBlendEquation");
2958         }
2959         break;
2960
2961     case D3DRS_TEXTUREFACTOR             :
2962         {
2963             int i;
2964
2965             /* Note the texture color applies to all textures whereas 
2966                GL_TEXTURE_ENV_COLOR applies to active only */
2967             float col[4];
2968             col[0] = ((Value >> 16) & 0xFF) / 255.0;
2969             col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2970             col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2971             col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2972
2973             /* Set the default alpha blend color */
2974             glBlendColor(col[0], col[1], col[2], col[3]);
2975             checkGLcall("glBlendColor");
2976
2977             /* And now the default texture color as well */
2978             for (i = 0; i < This->TextureUnits; i++) {
2979
2980                 /* Note the D3DRS value applies to all textures, but GL has one
2981                    per texture, so apply it now ready to be used!               */
2982                 if (This->isMultiTexture) {
2983 #if defined(GL_VERSION_1_3)
2984                     glActiveTexture(GL_TEXTURE0 + i);
2985 #else
2986                     glActiveTextureARB(GL_TEXTURE0_ARB + i);
2987 #endif
2988                     checkGLcall("Activate texture.. to update const color");
2989                 } else if (i>0) {
2990                     FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2991                 }
2992
2993                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2994                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2995             }
2996         }
2997         break;
2998
2999     case D3DRS_SPECULARENABLE            : 
3000         {
3001             if (Value) {
3002                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
3003                 checkGLcall("glLightModel (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);");
3004             } else {
3005                 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);
3006                 checkGLcall("glLightModel (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);");
3007             }
3008         }
3009         break;
3010
3011     case D3DRS_STENCILENABLE             :
3012         if (Value) {
3013             glEnable(GL_STENCIL_TEST);
3014             checkGLcall("glEnable GL_STENCIL_TEST");
3015         } else {
3016             glDisable(GL_STENCIL_TEST);
3017             checkGLcall("glDisable GL_STENCIL_TEST");
3018         }
3019         break;
3020
3021     case D3DRS_STENCILFUNC               :
3022         {
3023            int glParm = GL_ALWAYS;
3024            int ref = 0;
3025            GLuint mask = 0xFFFFFFFF;
3026
3027            glGetIntegerv(GL_STENCIL_REF, &ref);
3028            checkGLcall("glGetFloatv(GL_STENCIL_REF, &ref);");
3029            glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask);
3030            checkGLcall("glGetFloatv(GL_STENCIL_VALUE_MASK, &glParm);");
3031
3032            switch ((D3DCMPFUNC) Value) {
3033            case D3DCMP_NEVER:         glParm=GL_NEVER; break;
3034            case D3DCMP_LESS:          glParm=GL_LESS; break;
3035            case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
3036            case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
3037            case D3DCMP_GREATER:       glParm=GL_GREATER; break;
3038            case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
3039            case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
3040            case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
3041            default:
3042                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3043            }
3044            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3045            glStencilFunc(glParm, ref, mask);
3046            checkGLcall("glStencilFunc");
3047         }
3048         break;
3049
3050     case D3DRS_STENCILREF                :
3051         {
3052            int glParm = GL_ALWAYS;
3053            int ref = 0;
3054            GLuint mask = 0xFFFFFFFF;
3055
3056            glGetIntegerv(GL_STENCIL_FUNC, &glParm);
3057            checkGLcall("glGetFloatv(GL_STENCIL_FUNC, &glParm);");
3058            glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask);
3059            checkGLcall("glGetFloatv(GL_STENCIL_VALUE_MASK, &glParm);");
3060
3061            ref = Value;
3062            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3063            glStencilFunc(glParm, ref, mask);
3064            checkGLcall("glStencilFunc");
3065         }
3066         break;
3067
3068     case D3DRS_STENCILMASK               :
3069         {
3070            int glParm = GL_ALWAYS;
3071            int ref = 0.0;
3072            GLuint mask = Value;
3073
3074            glGetIntegerv(GL_STENCIL_REF, &ref);
3075            checkGLcall("glGetFloatv(GL_STENCIL_REF, &ref);");
3076            glGetIntegerv(GL_STENCIL_FUNC, &glParm);
3077            checkGLcall("glGetFloatv(GL_STENCIL_FUNC, &glParm);");
3078
3079            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3080            glStencilFunc(glParm, ref, mask);
3081            checkGLcall("glStencilFunc");
3082         }
3083         break;
3084
3085     case D3DRS_STENCILFAIL               :
3086         {
3087             GLenum fail  ; 
3088             GLenum zpass ; 
3089             GLenum zfail ; 
3090
3091             fail = StencilOp(Value);
3092             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3093             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3094             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3095             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3096
3097             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3098             glStencilOp(fail, zfail, zpass);
3099             checkGLcall("glStencilOp(fail, zfail, zpass);");
3100         }
3101         break;
3102     case D3DRS_STENCILZFAIL              :
3103         {
3104             GLenum fail  ; 
3105             GLenum zpass ; 
3106             GLenum zfail ; 
3107
3108             glGetIntegerv(GL_STENCIL_FAIL, &fail);
3109             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3110             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3111             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3112             zfail = StencilOp(Value);
3113
3114             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3115             glStencilOp(fail, zfail, zpass);
3116             checkGLcall("glStencilOp(fail, zfail, zpass);");
3117         }
3118         break;
3119     case D3DRS_STENCILPASS               :
3120         {
3121             GLenum fail  ; 
3122             GLenum zpass ; 
3123             GLenum zfail ; 
3124
3125             glGetIntegerv(GL_STENCIL_FAIL, &fail);
3126             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3127             zpass = StencilOp(Value);
3128             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3129             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3130
3131             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3132             glStencilOp(fail, zfail, zpass);
3133             checkGLcall("glStencilOp(fail, zfail, zpass);");
3134         }
3135         break;
3136
3137     case D3DRS_STENCILWRITEMASK          :
3138         {
3139             glStencilMask(Value);
3140             TRACE("glStencilMask(%lu)\n", Value);
3141             checkGLcall("glStencilMask");
3142         }
3143         break;
3144
3145     case D3DRS_FOGENABLE                 :
3146         {
3147             if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
3148                glEnable(GL_FOG);
3149                checkGLcall("glEnable GL_FOG\n");
3150             } else {
3151                glDisable(GL_FOG);
3152                checkGLcall("glDisable GL_FOG\n");
3153             }
3154         }
3155         break;
3156
3157     case D3DRS_FOGCOLOR                  :
3158         {
3159             float col[4];
3160             col[0] = ((Value >> 16) & 0xFF) / 255.0;
3161             col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
3162             col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
3163             col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
3164
3165             /* Set the default alpha blend color */
3166             glFogfv(GL_FOG_COLOR, &col[0]);
3167             checkGLcall("glFog GL_FOG_COLOR");
3168         }
3169         break;
3170
3171     case D3DRS_FOGSTART                  :
3172         {
3173             float *f = (float *)&Value;
3174             glFogfv(GL_FOG_START, f);
3175             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3176             TRACE("Fog Start == %f\n", *f);
3177         }
3178         break;
3179
3180     case D3DRS_FOGEND                    :
3181         {
3182             float *f = (float *)&Value;
3183             glFogfv(GL_FOG_END, f);
3184             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3185             TRACE("Fog End == %f\n", *f);
3186         }
3187         break;
3188
3189     case D3DRS_FOGDENSITY                :
3190         {
3191             glFogf(GL_FOG_DENSITY, (float) Value);
3192             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3193         }
3194         break;
3195
3196     case D3DRS_VERTEXBLEND               :
3197         {
3198           This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3199           TRACE("Vertex Blending state to %ld\n",  Value);
3200         }
3201         break;
3202
3203     case D3DRS_TWEENFACTOR               :
3204         {
3205           This->UpdateStateBlock->tween_factor = *((float*) &Value);
3206           TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
3207         }
3208         break;
3209
3210     case D3DRS_INDEXEDVERTEXBLENDENABLE  :
3211         {
3212           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3213         }
3214         break;
3215
3216
3217     case D3DRS_COLORVERTEX               :
3218     case D3DRS_DIFFUSEMATERIALSOURCE     :
3219     case D3DRS_SPECULARMATERIALSOURCE    :
3220     case D3DRS_AMBIENTMATERIALSOURCE     :
3221     case D3DRS_EMISSIVEMATERIALSOURCE    :
3222         {
3223             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3224
3225             if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
3226                 glEnable(GL_COLOR_MATERIAL);
3227                 checkGLcall("glEnable GL_GL_COLOR_MATERIAL\n");
3228
3229                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3230                       This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
3231                       This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
3232                       This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
3233                       This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
3234
3235                 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3236                     if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3237                         Parm = GL_AMBIENT_AND_DIFFUSE;
3238                     } else {
3239                         Parm = GL_DIFFUSE;
3240                     }
3241                 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3242                     Parm = GL_AMBIENT;
3243                 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3244                     Parm = GL_EMISSION;
3245                 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3246                     Parm = GL_SPECULAR;
3247                 } else {
3248                     Parm = -1;
3249                 }
3250
3251                 if (Parm == -1) {
3252                     glDisable(GL_COLOR_MATERIAL);
3253                     checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3254                 } else {
3255                     TRACE("glColorMaterial Parm=%d\n", Parm);
3256                     glColorMaterial(GL_FRONT_AND_BACK, Parm);
3257                     checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)\n");
3258                 }
3259
3260             } else {
3261                 glDisable(GL_COLOR_MATERIAL);
3262                 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3263             }
3264         }
3265         break; 
3266
3267         /* Unhandled yet...! */
3268     case D3DRS_LINEPATTERN               :
3269     case D3DRS_LASTPIXEL                 :
3270     case D3DRS_ZVISIBLE                  :
3271     case D3DRS_FOGTABLEMODE              :
3272     case D3DRS_EDGEANTIALIAS             :
3273     case D3DRS_ZBIAS                     :
3274     case D3DRS_RANGEFOGENABLE            :
3275     case D3DRS_WRAP0                     :
3276     case D3DRS_WRAP1                     :
3277     case D3DRS_WRAP2                     :
3278     case D3DRS_WRAP3                     :
3279     case D3DRS_WRAP4                     :
3280     case D3DRS_WRAP5                     :
3281     case D3DRS_WRAP6                     :
3282     case D3DRS_WRAP7                     :
3283     case D3DRS_FOGVERTEXMODE             :
3284     case D3DRS_LOCALVIEWER               :
3285     case D3DRS_NORMALIZENORMALS          :
3286     case D3DRS_SOFTWAREVERTEXPROCESSING  :
3287     case D3DRS_POINTSIZE                 :
3288     case D3DRS_POINTSIZE_MIN             :
3289     case D3DRS_POINTSPRITEENABLE         :
3290     case D3DRS_POINTSCALEENABLE          :
3291     case D3DRS_POINTSCALE_A              :
3292     case D3DRS_POINTSCALE_B              :
3293     case D3DRS_POINTSCALE_C              :
3294     case D3DRS_MULTISAMPLEANTIALIAS      :
3295     case D3DRS_MULTISAMPLEMASK           :
3296     case D3DRS_PATCHEDGESTYLE            :
3297     case D3DRS_PATCHSEGMENTS             :
3298     case D3DRS_DEBUGMONITORTOKEN         :
3299     case D3DRS_POINTSIZE_MAX             :
3300     case D3DRS_COLORWRITEENABLE          :
3301     case D3DRS_POSITIONORDER             :
3302     case D3DRS_NORMALORDER               :
3303         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3304         TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3305         break;
3306     default:
3307         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3308     }
3309
3310     return D3D_OK;
3311 }
3312 HRESULT  WINAPI  IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3313     ICOM_THIS(IDirect3DDevice8Impl,iface);
3314     TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3315     *pValue = This->StateBlock->renderstate[State];
3316     return D3D_OK;
3317 }
3318 HRESULT  WINAPI  IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3319   ICOM_THIS(IDirect3DDevice8Impl,iface);
3320   
3321   TRACE("(%p)\n", This);
3322   
3323   return IDirect3DDeviceImpl_BeginStateBlock(This);
3324 }
3325 HRESULT  WINAPI  IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3326   IDirect3DStateBlockImpl* pSB;
3327   ICOM_THIS(IDirect3DDevice8Impl,iface);
3328   HRESULT res;
3329
3330   TRACE("(%p)\n", This);
3331
3332   res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3333   *pToken = (DWORD) pSB;
3334   return res;
3335 }
3336
3337 HRESULT  WINAPI  IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3338   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3339   ICOM_THIS(IDirect3DDevice8Impl,iface);
3340
3341   TRACE("(%p)\n", This);
3342
3343   return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3344
3345 }
3346 HRESULT  WINAPI  IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3347   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3348   ICOM_THIS(IDirect3DDevice8Impl,iface);
3349
3350   TRACE("(%p)\n", This);
3351
3352   return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3353 }
3354 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3355   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3356   ICOM_THIS(IDirect3DDevice8Impl,iface);
3357
3358   TRACE("(%p)\n", This);
3359
3360   return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3361 }
3362
3363 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3364   IDirect3DStateBlockImpl* pSB;
3365   ICOM_THIS(IDirect3DDevice8Impl,iface);
3366   HRESULT res;
3367
3368   TRACE("(%p) : for type %d\n", This, Type);
3369
3370   res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3371   *pToken = (DWORD) pSB;
3372   return res;
3373 }
3374
3375 HRESULT  WINAPI  IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3376     ICOM_THIS(IDirect3DDevice8Impl,iface);
3377     FIXME("(%p) : stub\n", This);    return D3D_OK;
3378 }
3379 HRESULT  WINAPI  IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3380     ICOM_THIS(IDirect3DDevice8Impl,iface);
3381     FIXME("(%p) : stub\n", This);    return D3D_OK;
3382 }
3383 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3384     ICOM_THIS(IDirect3DDevice8Impl,iface);
3385     TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3386     *ppTexture = (LPDIRECT3DBASETEXTURE8)This->UpdateStateBlock->textures[Stage];
3387     IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3388     return D3D_OK;
3389 }
3390 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8* pTexture) {
3391
3392     IDirect3DBaseTexture8 *oldTxt;
3393     BOOL reapplyStates = TRUE;
3394
3395     ICOM_THIS(IDirect3DDevice8Impl,iface);
3396     D3DRESOURCETYPE textureType;
3397
3398     oldTxt = This->UpdateStateBlock->textures[Stage];
3399     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3400
3401     /* Reject invalid texture units */
3402     if (Stage >= This->TextureUnits) {
3403         TRACE("Attempt to access invalid texture rejected\n");
3404         return D3DERR_INVALIDCALL;
3405     }
3406
3407     This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3408     This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3409     This->UpdateStateBlock->textures[Stage] = pTexture;
3410
3411     /* Handle recording of state blocks */
3412     if (This->isRecordingState) {
3413         TRACE("Recording... not performing anything\n");
3414         return D3D_OK;
3415     }
3416
3417     /* Make appropriate texture active */
3418     if (This->isMultiTexture) {
3419 #if defined(GL_VERSION_1_3)
3420         glActiveTexture(GL_TEXTURE0 + Stage);
3421 #else
3422         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3423 #endif
3424         checkGLcall("glActiveTextureARB");
3425     } else if (Stage>0) {
3426         FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3427     }
3428
3429     /* Decrement the count of the previous texture */
3430     if (oldTxt != NULL) {
3431         IDirect3DBaseTexture8Impl_Release(oldTxt);
3432     }
3433
3434     if (pTexture) {
3435         IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8)This->UpdateStateBlock->textures[Stage]);
3436
3437         /* Now setup the texture appropraitly */
3438         textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3439
3440         if (textureType == D3DRTYPE_TEXTURE) {
3441           IDirect3DTexture8Impl *pTexture2 = (IDirect3DTexture8Impl *) pTexture;
3442
3443           if ((void *)oldTxt == (void *)pTexture2 && pTexture2->Dirty == FALSE) {
3444               TRACE("Skipping setting texture as old == new\n");
3445               reapplyStates = FALSE;
3446           } else {
3447
3448             /* Standard 2D texture */
3449             TRACE("Standard 2d texture\n");
3450             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3451
3452             /* Load up the texture now */
3453             IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8)pTexture);
3454           }
3455         } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3456             IDirect3DVolumeTexture8Impl *pTexture2 = (IDirect3DVolumeTexture8Impl *) pTexture;
3457             int i;
3458
3459             /* Standard 3D (volume) texture */
3460             TRACE("Standard 3d texture\n");
3461             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3462
3463             for (i=0; i<pTexture2->levels; i++) 
3464             {
3465
3466                 if (i==0 && pTexture2->volumes[i]->textureName != 0 && pTexture2->Dirty == FALSE) {
3467                     glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3468                     checkGLcall("glBindTexture");
3469                     TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3470
3471                     /* No need to walk through all mip-map levels, since already all assigned */
3472                     i = pTexture2->levels;
3473                 } else {
3474                     if (i==0) {
3475
3476                         if (pTexture2->volumes[i]->textureName == 0) {
3477                             glGenTextures(1, &pTexture2->volumes[i]->textureName);
3478                             checkGLcall("glGenTextures");
3479                             TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3480                         }
3481
3482                         glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3483                         checkGLcall("glBindTexture");
3484
3485                         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1); 
3486                         checkGLcall("glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1)");
3487                     }
3488
3489                     TRACE("Calling glTexImage3D %x i=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%lx, Mem=%p\n",
3490                           GL_TEXTURE_3D, i, fmt2glintFmt(pTexture2->format), pTexture2->volumes[i]->myDesc.Width,
3491                           pTexture2->volumes[i]->myDesc.Height, pTexture2->volumes[i]->myDesc.Depth,
3492                           0, fmt2glFmt(pTexture2->format),fmt2glType(pTexture2->format),
3493                           pTexture2->volumes[i]->allocatedMemory);
3494                     glTexImage3D(GL_TEXTURE_3D, i,
3495                                  fmt2glintFmt(pTexture2->format),
3496                                  pTexture2->volumes[i]->myDesc.Width,
3497                                  pTexture2->volumes[i]->myDesc.Height,
3498                                  pTexture2->volumes[i]->myDesc.Depth,
3499                                  0,
3500                                  fmt2glFmt(pTexture2->format),
3501                                  fmt2glType(pTexture2->format),
3502                                  pTexture2->volumes[i]->allocatedMemory
3503                                 );
3504                     checkGLcall("glTexImage3D");
3505
3506                     /* Removed glTexParameterf now TextureStageStates are initialized at startup */
3507                     pTexture2->Dirty = FALSE;
3508                 }
3509             }
3510
3511         } else {
3512             FIXME("(%p) : Incorrect type for a texture : %d\n", This, textureType);
3513         }
3514     } else {
3515         TRACE("Setting to no texture (ie default texture)\n");
3516         This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3517         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3518         checkGLcall("glBindTexture");
3519         TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3520     }
3521
3522     /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3523        a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3524     if (reapplyStates) {
3525        setupTextureStates (iface, Stage);
3526     }
3527        
3528     return D3D_OK;
3529 }
3530
3531 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3532     ICOM_THIS(IDirect3DDevice8Impl,iface);
3533     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3534     *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3535     return D3D_OK;
3536 }
3537
3538 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) {
3539     ICOM_THIS(IDirect3DDevice8Impl,iface);
3540
3541     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3542    
3543     TRACE("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value);
3544
3545     /* Reject invalid texture units */
3546     if (Stage >= This->TextureUnits) {
3547         TRACE("Attempt to access invalid texture rejected\n");
3548         return D3DERR_INVALIDCALL;
3549     }
3550
3551     This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3552     This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3553     This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3554
3555     /* Handle recording of state blocks */
3556     if (This->isRecordingState) {
3557         TRACE("Recording... not performing anything\n");
3558         return D3D_OK;
3559     }
3560
3561     /* Make appropriate texture active */
3562     VTRACE(("Activating appropriate texture state %ld\n", Stage));
3563     if (This->isMultiTexture) {
3564 #if defined(GL_VERSION_1_3)
3565         glActiveTexture(GL_TEXTURE0 + Stage);
3566         vcheckGLcall("glActiveTexture");
3567 #else
3568         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3569         vcheckGLcall("glActiveTextureARB");
3570 #endif
3571     } else if (Stage > 0) {
3572         FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3573     }
3574
3575     switch (Type) {
3576
3577     case D3DTSS_MINFILTER             :
3578     case D3DTSS_MIPFILTER             :
3579         {
3580             DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3581             DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3582             GLint realVal = GL_LINEAR;
3583
3584             if (ValueMIN == D3DTEXF_POINT) {
3585                 /* GL_NEAREST_* */
3586                 if (ValueMIP == D3DTEXF_POINT) {
3587                     realVal = GL_NEAREST_MIPMAP_NEAREST;
3588                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3589                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3590                 } else if (ValueMIP == D3DTEXF_NONE) {
3591                     realVal = GL_NEAREST;
3592                 } else {
3593                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3594                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3595                 }
3596             } else if (ValueMIN == D3DTEXF_LINEAR) {
3597                 /* GL_LINEAR_* */
3598                 if (ValueMIP == D3DTEXF_POINT) {
3599                     realVal = GL_LINEAR_MIPMAP_NEAREST;
3600                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3601                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3602                 } else if (ValueMIP == D3DTEXF_NONE) {
3603                     realVal = GL_LINEAR;
3604                 } else {
3605                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3606                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3607                 }
3608             } else if (ValueMIN == D3DTEXF_NONE) {
3609                 /* Doesnt really make sense - Windows just seems to disable
3610                    mipmapping when this occurs                              */
3611                 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3612                 realVal = GL_LINEAR;
3613
3614             } else {
3615                 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3616                 realVal = GL_LINEAR_MIPMAP_LINEAR;
3617             }
3618
3619             TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3620             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3621             checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3622         }
3623         break;
3624
3625
3626     case D3DTSS_MAGFILTER             :
3627         if (Value == D3DTEXF_POINT) {
3628             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3629             checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3630         } else if (Value == D3DTEXF_LINEAR) {
3631             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3632             checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3633         } else {
3634             FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3635         }
3636         break;
3637
3638     case D3DTSS_COLORARG0             :
3639     case D3DTSS_ALPHAARG0             :
3640         /* FIXME: Mesa seems to struggle setting these at the moment */
3641         /*FIXME("COLORARG0/ALPHAARG0 support still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);*/
3642         /*break;*/
3643
3644     case D3DTSS_COLORARG1             :
3645     case D3DTSS_COLORARG2             :
3646     case D3DTSS_ALPHAARG1             :
3647     case D3DTSS_ALPHAARG2             :
3648         {
3649             BOOL isAlphaArg = (Type == D3DTSS_ALPHAARG1 || Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3650             int  operand = GL_SRC_COLOR;
3651             int  source = GL_TEXTURE;
3652
3653             GetSrcAndOpFromValue(Value, isAlphaArg, &source, &operand);
3654             if (isAlphaArg) {
3655                 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_ALPHA_EXT(Type), source, OPERANDx_ALPHA_EXT(Type), operand);
3656                 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT(Type), source);
3657                 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT, source);");
3658                 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT(Type), operand);
3659                 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT, operand);");
3660             } else {
3661                 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_RGB_EXT(Type), source, OPERANDx_RGB_EXT(Type), operand);
3662                 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT(Type), source);
3663                 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT, source);");
3664                 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT(Type), operand);
3665                 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT, operand);");
3666             }
3667         }
3668         break;
3669
3670     case D3DTSS_ALPHAOP               :
3671     case D3DTSS_COLOROP               :
3672         {
3673
3674             int Scale = 1;
3675             int Parm = (Type == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
3676
3677             if (Type == D3DTSS_COLOROP && Value == D3DTOP_DISABLE) {
3678                 /* TODO: Disable by making this and all later levels disabled */
3679                 glDisable(GL_TEXTURE_1D);
3680                 checkGLcall("Disable GL_TEXTURE_1D");
3681                 glDisable(GL_TEXTURE_2D);
3682                 checkGLcall("Disable GL_TEXTURE_2D");
3683                 glDisable(GL_TEXTURE_3D);
3684                 checkGLcall("Disable GL_TEXTURE_3D");
3685             } else {
3686
3687                 /* Enable only the appropriate texture dimension */
3688                 if (Type == D3DTSS_COLOROP) {
3689                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3690                         glEnable(GL_TEXTURE_1D);
3691                         checkGLcall("Enable GL_TEXTURE_1D");
3692                     } else {
3693                         glDisable(GL_TEXTURE_1D);
3694                         checkGLcall("Disable GL_TEXTURE_1D");
3695                     } 
3696                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3697                         glEnable(GL_TEXTURE_2D);
3698                         checkGLcall("Enable GL_TEXTURE_2D");
3699                     } else {
3700                         glDisable(GL_TEXTURE_2D);
3701                         checkGLcall("Disable GL_TEXTURE_2D");
3702                     }
3703                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3704                         glEnable(GL_TEXTURE_3D);
3705                         checkGLcall("Enable GL_TEXTURE_3D");
3706                     } else {
3707                         glDisable(GL_TEXTURE_3D);
3708                         checkGLcall("Disable GL_TEXTURE_3D");
3709                     }
3710                 }
3711
3712                 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
3713                 if (Value != D3DTOP_DISABLE) {
3714                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
3715                 }
3716
3717                 /* Now set up the operand correctly */
3718                 switch (Value) {
3719                 case D3DTOP_DISABLE                   :
3720                     /* Contrary to the docs, alpha can be disabled when colorop is enabled
3721                        and it works, so ignore this op */
3722                     TRACE("Disable ALPHAOP but COLOROP enabled!\n");
3723                     break;
3724
3725                 case D3DTOP_SELECTARG1                :
3726                     {
3727                         glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
3728                         checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
3729 #if 0 /* don't seem to do anything */                   
3730                         BOOL  isAlphaOp = (Type == D3DTSS_ALPHAOP);
3731                         DWORD dwValue = 0;
3732                         GLenum source;
3733                         GLenum operand;                 
3734                         dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG1 : D3DTSS_COLORARG1];
3735                         GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3736                         if (isAlphaOp) {
3737                           TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_ALPHA_EXT, source, GL_OPERAND0_ALPHA_EXT, operand);
3738                           glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, source);
3739                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, 'source')");
3740                           glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, operand);
3741                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, 'operand')");
3742                         } else {
3743                           TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_RGB_EXT, source, GL_OPERAND0_RGB_EXT, operand);
3744                           glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, source);
3745                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, 'source')");
3746                           glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, operand);
3747                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, 'operand')");
3748                         }
3749                         dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG2 : D3DTSS_COLORARG2];
3750                         GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3751                         if (isAlphaOp) {
3752                           TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_ALPHA_EXT, source, GL_OPERAND1_ALPHA_EXT, operand);
3753                           glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, source);
3754                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, 'source')");
3755                           glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, operand);
3756                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, 'operand')");
3757                         } else {
3758                           TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_RGB_EXT, source, GL_OPERAND1_RGB_EXT, operand);
3759                           glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, source);
3760                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, 'source')");
3761                           glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, operand);
3762                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, 'operand')");
3763                         }
3764 #endif                  
3765                     }
3766                     break;
3767
3768                 case D3DTOP_SELECTARG2                :
3769                     { 
3770                         BOOL  isAlphaOp = (Type == D3DTSS_ALPHAOP);
3771                         DWORD dwValue = 0;
3772                         GLenum source;
3773                         GLenum operand;
3774                         glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
3775                         checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
3776                         /* GL_REPLACE, swap args 0 and 1? */
3777                         dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG2 : D3DTSS_COLORARG2];
3778                         GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3779                         if (isAlphaOp) {
3780                           TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_ALPHA_EXT, source, GL_OPERAND0_ALPHA_EXT, operand);
3781                           glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, source);
3782                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, 'source')");
3783                           glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, operand);
3784                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, 'operand')");
3785                         } else {
3786                           TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_RGB_EXT, source, GL_OPERAND0_RGB_EXT, operand);
3787                           glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, source);
3788                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, 'source')");
3789                           glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, operand);
3790                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, 'operand')");
3791                         }
3792                         dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG1 : D3DTSS_COLORARG1];
3793                         GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3794                         if (isAlphaOp) {
3795                           TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_ALPHA_EXT, source, GL_OPERAND1_ALPHA_EXT, operand);
3796                           glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, source);
3797                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, 'source')");
3798                           glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, operand);
3799                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, 'operand')");
3800                         } else {
3801                           TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_RGB_EXT, source, GL_OPERAND1_RGB_EXT, operand);
3802                           glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, source);
3803                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, 'source')");
3804                           glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, operand);
3805                           checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, 'operand')");
3806                         }
3807                     }
3808                     break;
3809
3810                 case D3DTOP_MODULATE4X                : Scale = Scale * 2;  /* Drop through */
3811                 case D3DTOP_MODULATE2X                : Scale = Scale * 2;  /* Drop through */
3812                 case D3DTOP_MODULATE                  :
3813
3814                     /* Correct scale */
3815                     if (Type == D3DTSS_ALPHAOP) {
3816                         glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale);
3817                         vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale)");
3818                     } else {
3819                         glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale);
3820                         vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale)");
3821                     }
3822                     glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);
3823                     checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);");
3824                     break;
3825
3826                 case D3DTOP_ADD                       :
3827                     glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD);
3828                     vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD)");
3829                     break;
3830
3831                 case D3DTOP_ADDSIGNED2X               : Scale = Scale * 2;  /* Drop through */
3832                 case D3DTOP_ADDSIGNED                 :
3833                     glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT);
3834                     vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT)");
3835                     break;
3836
3837                 case D3DTOP_DOTPRODUCT3               :
3838 #if defined(GL_VERSION_1_3)
3839                     if (This->isDot3) {
3840                         glTexEnvi(GL_TEXTURE_ENV, Parm, GL_DOT3_RGBA);
3841                         checkGLcall("glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA);");
3842                         break;
3843                     }
3844 #endif
3845                     FIXME("DotProduct3 extension requested but not supported via this version of opengl\n");
3846                     break;
3847
3848                 case D3DTOP_SUBTRACT                  :
3849 #if defined(GL_VERSION_1_3)
3850                     glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT);
3851                     checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT)");
3852                     break;
3853 #else
3854                     /**
3855                      * @TODO: to check:
3856                      *  if ARB_texture_env_combine is supported
3857                      *   we can use GL_SUBTRACT_ARB here
3858                      */
3859 #endif
3860                 case D3DTOP_ADDSMOOTH                 :
3861                 case D3DTOP_BLENDDIFFUSEALPHA         :
3862                 case D3DTOP_BLENDTEXTUREALPHA         :
3863                 case D3DTOP_BLENDFACTORALPHA          :
3864                 case D3DTOP_BLENDTEXTUREALPHAPM       :
3865                 case D3DTOP_BLENDCURRENTALPHA         :
3866                 case D3DTOP_PREMODULATE               :
3867                 case D3DTOP_MODULATEALPHA_ADDCOLOR    :
3868                 case D3DTOP_MODULATECOLOR_ADDALPHA    :
3869                 case D3DTOP_MODULATEINVALPHA_ADDCOLOR :
3870                 case D3DTOP_MODULATEINVCOLOR_ADDALPHA :
3871                 case D3DTOP_BUMPENVMAP                :
3872                 case D3DTOP_BUMPENVMAPLUMINANCE       :
3873                 case D3DTOP_MULTIPLYADD               :
3874                 case D3DTOP_LERP                      :
3875                 default:
3876                     FIXME("Unhandled texture operation %ld\n", Value);
3877                 }
3878             }
3879             break;
3880         }
3881
3882     case D3DTSS_ADDRESSU              :
3883     case D3DTSS_ADDRESSV              :
3884     case D3DTSS_ADDRESSW              :
3885         {
3886             GLint wrapParm = GL_REPEAT;
3887             switch (Value) {
3888             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
3889             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;      
3890             case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break;      /* FIXME: Not right, but better */
3891 #if defined(GL_VERSION_1_4)
3892             case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3893 #elif defined(GL_ARB_texture_mirrored_repeat)
3894             case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3895 #else
3896             case D3DTADDRESS_MIRROR:      /* Unsupported in OpenGL pre-1.4 */
3897 #endif
3898             case D3DTADDRESS_MIRRORONCE:  /* Unsupported in OpenGL         */
3899             default:
3900                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3901                 wrapParm = GL_REPEAT; 
3902             }
3903
3904             switch (Type) {
3905             case D3DTSS_ADDRESSU:
3906                 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3907                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3908                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3909                 break;
3910             case D3DTSS_ADDRESSV:
3911                 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3912                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3913                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3914                 break;
3915             case D3DTSS_ADDRESSW:
3916                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3917                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3918                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3919                 break;
3920             default: /* nop */
3921                 break; /** stupic compilator */
3922             }
3923         }
3924         break;
3925
3926     case D3DTSS_BORDERCOLOR           :
3927         {
3928             float col[4];
3929             col[0] = ((Value >> 16) & 0xFF) / 255.0;
3930             col[1] = ((Value >>  8) & 0xFF) / 255.0;
3931             col[2] = ((Value >>  0) & 0xFF) / 255.0;
3932             col[3] = ((Value >> 24) & 0xFF) / 255.0;
3933
3934             TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value); 
3935             glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3936             checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3937         }
3938         break;
3939
3940     case D3DTSS_TEXCOORDINDEX         :
3941         {
3942             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3943           
3944             /** 
3945              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos 
3946              */
3947             switch (Value & 0xFFFFFF00) {
3948             case D3DTSS_TCI_PASSTHRU:
3949               /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3950               break;
3951
3952             case D3DTSS_TCI_CAMERASPACEPOSITION:
3953               /* CameraSpacePosition means use the vertex position, transformed to camera space, 
3954                  as the input texture coordinates for this stage's texture transformation. This 
3955                  equates roughly to EYE_LINEAR                                                  */
3956               {
3957                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3958                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3959                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3960                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3961                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3962
3963                 glMatrixMode(GL_MODELVIEW);
3964                 glPushMatrix();
3965                 glLoadIdentity();
3966                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3967                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3968                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3969                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3970                 glPopMatrix();
3971                 
3972                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3973                 glEnable(GL_TEXTURE_GEN_S);
3974                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3975                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3976                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3977                 glEnable(GL_TEXTURE_GEN_T);
3978                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3979                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3980                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3981                 glEnable(GL_TEXTURE_GEN_R);
3982                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3983                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3984                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3985               }
3986               break;
3987
3988             default:
3989                 /* Todo: */
3990                 /* ? disable GL_TEXTURE_GEN_n ? */
3991                 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3992                 break;
3993             }
3994         }
3995         break;
3996
3997         /* Unhandled */
3998     case D3DTSS_BUMPENVMAT00          :
3999     case D3DTSS_BUMPENVMAT01          :
4000       TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
4001       break;
4002     case D3DTSS_BUMPENVMAT10          :
4003     case D3DTSS_BUMPENVMAT11          :
4004       TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
4005       break;
4006
4007     case D3DTSS_MIPMAPLODBIAS         :
4008     case D3DTSS_MAXMIPLEVEL           :
4009     case D3DTSS_MAXANISOTROPY         :
4010     case D3DTSS_BUMPENVLSCALE         :
4011     case D3DTSS_BUMPENVLOFFSET        :
4012     case D3DTSS_TEXTURETRANSFORMFLAGS :
4013     case D3DTSS_RESULTARG             :
4014     default:
4015         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4016         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4017     }
4018     return D3D_OK;
4019 }
4020 HRESULT  WINAPI  IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
4021     ICOM_THIS(IDirect3DDevice8Impl,iface);
4022     TRACE("(%p) : stub\n", This);    /* FIXME: Needs doing, but called often and is harmless */
4023     return D3D_OK;
4024 }
4025 HRESULT  WINAPI  IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID,void* pDevInfoStruct,DWORD DevInfoStructSize) {
4026     ICOM_THIS(IDirect3DDevice8Impl,iface);
4027     FIXME("(%p) : stub\n", This);    return D3D_OK;
4028 }
4029 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,CONST PALETTEENTRY* pEntries) {
4030     ICOM_THIS(IDirect3DDevice8Impl,iface);
4031     FIXME("(%p) : stub\n", This);    return D3D_OK;
4032 }
4033 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,PALETTEENTRY* pEntries) {
4034     ICOM_THIS(IDirect3DDevice8Impl,iface);
4035     FIXME("(%p) : stub\n", This);    return D3D_OK;
4036 }
4037 HRESULT  WINAPI  IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
4038     ICOM_THIS(IDirect3DDevice8Impl,iface);
4039     FIXME("(%p) : stub\n", This);    return D3D_OK;
4040 }
4041 HRESULT  WINAPI  IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
4042     ICOM_THIS(IDirect3DDevice8Impl,iface);
4043     FIXME("(%p) : stub\n", This);    return D3D_OK;
4044 }
4045 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) {
4046
4047     IDirect3DVertexBuffer8     *pVB;
4048
4049     ICOM_THIS(IDirect3DDevice8Impl,iface);
4050     pVB = This->StateBlock->stream_source[0];
4051
4052     TRACE("(%p) : Type=%d, Start=%d, Count=%d\n", This, PrimitiveType, StartVertex, PrimitiveCount);
4053
4054     DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE,
4055                    This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory, StartVertex, -1, 0, NULL, 0);
4056
4057     return D3D_OK;
4058 }
4059 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
4060                                                            UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
4061     UINT idxStride = 2;
4062     IDirect3DIndexBuffer8      *pIB;
4063     IDirect3DVertexBuffer8     *pVB;
4064     D3DINDEXBUFFER_DESC         IdxBufDsc;
4065
4066     ICOM_THIS(IDirect3DDevice8Impl,iface);
4067     pIB = This->StateBlock->pIndexData;
4068     pVB = This->StateBlock->stream_source[0];
4069
4070     TRACE("(%p) : Type=%d, min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, PrimitiveType,
4071           minIndex, NumVertices, startIndex, primCount);
4072
4073     IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
4074     if (IdxBufDsc.Format == D3DFMT_INDEX16) {
4075         idxStride = 2;
4076     } else {
4077         idxStride = 4;
4078     }
4079
4080     DrawPrimitiveI(iface, PrimitiveType, primCount, TRUE, This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory,
4081                    This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
4082                    minIndex);
4083
4084     return D3D_OK;
4085 }
4086 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
4087     ICOM_THIS(IDirect3DDevice8Impl,iface);
4088
4089     TRACE("(%p) : Type=%d, pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4090
4091     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4092
4093     This->StateBlock->stream_source[0] = NULL;
4094     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4095     DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4096                    0, 0, 0, NULL, 0);
4097     This->StateBlock->stream_stride[0] = 0;
4098
4099     /*stream zero settings set to null at end */
4100     return D3D_OK;
4101 }
4102 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
4103                                                              UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4104                                                              D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4105                                                              UINT VertexStreamZeroStride) {
4106     int idxStride;
4107     ICOM_THIS(IDirect3DDevice8Impl,iface);
4108     TRACE("(%p) : Type=%d, MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType,
4109           MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,  IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4110
4111     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4112     if (IndexDataFormat == D3DFMT_INDEX16) {
4113         idxStride = 2;
4114     } else {
4115         idxStride = 4;
4116     }
4117
4118     This->StateBlock->stream_source[0] = NULL;
4119     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4120     DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, TRUE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4121                    This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
4122
4123     /*stream zero settings set to null at end */
4124     This->StateBlock->stream_stride[0] = 0;
4125     IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
4126
4127     return D3D_OK;
4128 }
4129 HRESULT  WINAPI  IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
4130     ICOM_THIS(IDirect3DDevice8Impl,iface);
4131     FIXME("(%p) : stub\n", This);    return D3D_OK;
4132 }
4133 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
4134     ICOM_THIS(IDirect3DDevice8Impl,iface);
4135     IDirect3DVertexShaderImpl* object;
4136     IDirect3DVertexShaderDeclarationImpl* attached_decl;
4137     HRESULT res;
4138     UINT i;
4139
4140     TRACE("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p\n", This, pDeclaration, pFunction);    
4141     if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
4142       return D3DERR_INVALIDCALL;
4143     }
4144     for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
4145     if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
4146       return D3DERR_OUTOFVIDEOMEMORY;
4147     }
4148
4149     /** Create the Vertex Shader */
4150     res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
4151     /** TODO: check FAILED(res) */
4152
4153     /** Create and Bind the Vertex Shader Declaration */
4154     res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
4155     /** TODO: check FAILED(res) */
4156
4157     VertexShaders[i] = object;
4158     VertexShaderDeclarations[i] = attached_decl;
4159     *pHandle = VS_HIGHESTFIXEDFXF + i;
4160
4161     return D3D_OK;
4162 }
4163 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4164     ICOM_THIS(IDirect3DDevice8Impl,iface);
4165
4166     This->UpdateStateBlock->VertexShader = Handle;
4167     This->UpdateStateBlock->Changed.vertexShader = TRUE;
4168     This->UpdateStateBlock->Set.vertexShader = TRUE;
4169     
4170     if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4171       FIXME("(%p) : Created shader, Handle=%lx\n", This, Handle);
4172       This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4173       This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4174       This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4175     } else { /* use a fvf, so desactivate the vshader decl */
4176       TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4177       This->UpdateStateBlock->vertexShaderDecl = NULL;
4178       This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4179       This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4180     }
4181     /* Handle recording of state blocks */
4182     if (This->isRecordingState) {
4183       TRACE("Recording... not performing anything\n");
4184       return D3D_OK;
4185     }
4186     /**
4187      * TODO: merge HAL shaders context switching from prototype
4188      */
4189     return D3D_OK;
4190 }
4191 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4192     ICOM_THIS(IDirect3DDevice8Impl,iface);
4193     TRACE("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4194     *pHandle = This->StateBlock->VertexShader;
4195     return D3D_OK;
4196 }
4197
4198 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4199     ICOM_THIS(IDirect3DDevice8Impl,iface);
4200     IDirect3DVertexShaderImpl* object; 
4201     IDirect3DVertexShaderDeclarationImpl* attached_decl;
4202
4203     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4204       return D3DERR_INVALIDCALL;
4205     }
4206
4207     /**
4208      * Delete Vertex Shader
4209      */
4210     object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4211     if (NULL == object) {
4212       return D3DERR_INVALIDCALL;
4213     }
4214     FIXME("(%p) : freing VertexShader %p\n", This, object);
4215     /* TODO: check validity of object */
4216     if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4217     HeapFree(GetProcessHeap(), 0, (void *)object->data);
4218     HeapFree(GetProcessHeap(), 0, (void *)object);
4219     VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4220
4221     /**
4222      * Delete Vertex Shader Declaration
4223      */
4224     attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4225     if (NULL == attached_decl) {
4226       return D3DERR_INVALIDCALL;
4227     } 
4228     FIXME("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4229     /* TODO: check validity of object */
4230     HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4231     HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4232     VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4233
4234     return D3D_OK;
4235 }
4236
4237 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4238   ICOM_THIS(IDirect3DDevice8Impl,iface);
4239
4240   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4241     ERR("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4242     return D3DERR_INVALIDCALL;
4243   }
4244   if (NULL == pConstantData) {
4245     return D3DERR_INVALIDCALL;
4246   }
4247   if (ConstantCount > 1) {
4248     FLOAT* f = (FLOAT*)pConstantData;
4249     UINT i;
4250     TRACE("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4251     for (i = 0; i < ConstantCount; ++i) {
4252       TRACE("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4253       f += 4;
4254     }
4255   } else { 
4256     FLOAT* f = (FLOAT*)pConstantData;
4257     TRACE("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4258   }
4259   This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4260   memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4261   return D3D_OK;
4262 }
4263 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4264   ICOM_THIS(IDirect3DDevice8Impl,iface);
4265
4266   TRACE("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4267   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4268     return D3DERR_INVALIDCALL;
4269   }
4270   if (NULL == pConstantData) {
4271     return D3DERR_INVALIDCALL;
4272   }
4273   memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4274   return D3D_OK;
4275 }
4276 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4277   /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4278   IDirect3DVertexShaderDeclarationImpl* attached_decl;
4279   
4280   attached_decl = VERTEX_SHADER_DECL(Handle);
4281   if (NULL == attached_decl) {
4282     return D3DERR_INVALIDCALL;
4283   }
4284   return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4285 }
4286 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4287   /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4288   IDirect3DVertexShaderImpl* object;
4289   
4290   object = VERTEX_SHADER(Handle);
4291   if (NULL == object) {
4292     return D3DERR_INVALIDCALL;
4293   }
4294   return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4295 }
4296
4297 HRESULT  WINAPI  IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4298     ICOM_THIS(IDirect3DDevice8Impl,iface);
4299     IDirect3DIndexBuffer8 *oldIdxs;
4300
4301     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4302     oldIdxs = This->StateBlock->pIndexData;
4303
4304     This->UpdateStateBlock->Changed.Indices = TRUE;
4305     This->UpdateStateBlock->Set.Indices = TRUE;
4306     This->UpdateStateBlock->pIndexData = pIndexData;
4307     This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4308
4309     /* Handle recording of state blocks */
4310     if (This->isRecordingState) {
4311         TRACE("Recording... not performing anything\n");
4312         return D3D_OK;
4313     }
4314
4315     if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4316     if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4317     return D3D_OK;
4318 }
4319 HRESULT  WINAPI  IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4320     ICOM_THIS(IDirect3DDevice8Impl,iface);
4321     FIXME("(%p) : stub\n", This);
4322
4323     *ppIndexData = This->StateBlock->pIndexData;
4324     /* up ref count on ppindexdata */
4325     if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4326     *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4327
4328     return D3D_OK;
4329 }
4330 HRESULT  WINAPI  IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4331     ICOM_THIS(IDirect3DDevice8Impl,iface);
4332     IDirect3DPixelShaderImpl* object;
4333     UINT i;
4334
4335     FIXME("(%p) : PixelShader not fully supported yet\n", This);    
4336     if (NULL == pFunction || NULL == pHandle) {
4337       return D3DERR_INVALIDCALL;
4338     }
4339     for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4340     if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4341       return D3DERR_OUTOFVIDEOMEMORY;
4342     }
4343     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DPixelShaderImpl));
4344     if (NULL == object) {
4345       return D3DERR_OUTOFVIDEOMEMORY;
4346     }
4347     
4348     object->data = NULL; /* TODO */
4349
4350     PixelShaders[i] = object;
4351     *pHandle = VS_HIGHESTFIXEDFXF + i;
4352
4353     object->function = pFunction;
4354     for (i = 0; 0xFFFFFFFF != pFunction[i]; ++i) ;
4355     object->functionLength = i + 1;
4356
4357     return D3D_OK;
4358 }
4359 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4360     ICOM_THIS(IDirect3DDevice8Impl,iface);
4361
4362     This->UpdateStateBlock->PixelShader = Handle;
4363     This->UpdateStateBlock->Changed.pixelShader = TRUE;
4364     This->UpdateStateBlock->Set.pixelShader = TRUE;
4365
4366     /* Handle recording of state blocks */
4367     if (This->isRecordingState) {
4368         TRACE("Recording... not performing anything\n");
4369         return D3D_OK;
4370     }
4371
4372     /* FIXME: Quieten when not being used */
4373     if (Handle != 0) {
4374       FIXME("(%p) : stub %ld\n", This, Handle);
4375     } else {
4376       TRACE("(%p) : stub %ld\n", This, Handle);
4377     }
4378
4379     return D3D_OK;
4380 }
4381 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4382     ICOM_THIS(IDirect3DDevice8Impl,iface);
4383     TRACE("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4384     *pHandle = This->StateBlock->PixelShader;
4385     return D3D_OK;
4386 }
4387
4388 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4389     ICOM_THIS(IDirect3DDevice8Impl,iface);
4390     IDirect3DPixelShaderImpl* object;   
4391
4392     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4393       return D3DERR_INVALIDCALL;
4394     }
4395     object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4396     TRACE("(%p) : freeing PixelShader %p\n", This, object);
4397     /* TODO: check validity of object before free */
4398     HeapFree(GetProcessHeap(), 0, (void *)object);
4399     PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = 0;
4400     return D3D_OK;
4401 }
4402
4403 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,CONST void* pConstantData, DWORD ConstantCount) {
4404     ICOM_THIS(IDirect3DDevice8Impl,iface);
4405     FIXME("(%p) : stub\n", This);
4406     return D3D_OK;
4407 }
4408 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,void* pConstantData, DWORD ConstantCount) {
4409     ICOM_THIS(IDirect3DDevice8Impl,iface);
4410     FIXME("(%p) : stub\n", This);  
4411     return D3D_OK;
4412 }
4413 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4414     ICOM_THIS(IDirect3DDevice8Impl,iface);
4415     IDirect3DPixelShaderImpl* object;
4416
4417     object = PIXEL_SHADER(Handle);
4418     if (NULL == object) {
4419       return D3DERR_INVALIDCALL;
4420     }
4421     if (NULL == pData) {
4422       *pSizeOfData = object->functionLength;
4423       return D3D_OK;
4424     }
4425     if (*pSizeOfData < object->functionLength) {
4426       *pSizeOfData = object->functionLength;
4427       return D3DERR_MOREDATA;
4428     }
4429     TRACE("(%p) : GetPixelShaderFunction copying to %p\n", This, pData);
4430     memcpy(pData, object->function, object->functionLength);
4431     return D3D_OK;
4432 }
4433 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4434     ICOM_THIS(IDirect3DDevice8Impl,iface);
4435     FIXME("(%p) : stub\n", This);    return D3D_OK;
4436 }
4437 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4438     ICOM_THIS(IDirect3DDevice8Impl,iface);
4439     FIXME("(%p) : stub\n", This);    return D3D_OK;
4440 }
4441 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4442     ICOM_THIS(IDirect3DDevice8Impl,iface);
4443     FIXME("(%p) : stub\n", This);    return D3D_OK;
4444 }
4445
4446 HRESULT  WINAPI  IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4447     IDirect3DVertexBuffer8 *oldSrc;
4448     ICOM_THIS(IDirect3DDevice8Impl,iface);
4449
4450     oldSrc = This->StateBlock->stream_source[StreamNumber];
4451     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4452
4453     This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4454     This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4455     This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4456     This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4457
4458     /* Handle recording of state blocks */
4459     if (This->isRecordingState) {
4460         TRACE("Recording... not performing anything\n");
4461         return D3D_OK;
4462     }
4463
4464     if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4465     if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4466     return D3D_OK;
4467 }
4468 HRESULT  WINAPI  IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4469     ICOM_THIS(IDirect3DDevice8Impl,iface);
4470     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4471     *pStream = This->StateBlock->stream_source[StreamNumber];
4472     *pStride = This->StateBlock->stream_stride[StreamNumber];
4473     IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4474     return D3D_OK;
4475 }
4476
4477
4478 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4479 {
4480     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4481     IDirect3DDevice8Impl_QueryInterface,
4482     IDirect3DDevice8Impl_AddRef,
4483     IDirect3DDevice8Impl_Release,
4484     IDirect3DDevice8Impl_TestCooperativeLevel,
4485     IDirect3DDevice8Impl_GetAvailableTextureMem,
4486     IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4487     IDirect3DDevice8Impl_GetDirect3D,
4488     IDirect3DDevice8Impl_GetDeviceCaps,
4489     IDirect3DDevice8Impl_GetDisplayMode,
4490     IDirect3DDevice8Impl_GetCreationParameters,
4491     IDirect3DDevice8Impl_SetCursorProperties,
4492     IDirect3DDevice8Impl_SetCursorPosition,
4493     IDirect3DDevice8Impl_ShowCursor,
4494     IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4495     IDirect3DDevice8Impl_Reset,
4496     IDirect3DDevice8Impl_Present,
4497     IDirect3DDevice8Impl_GetBackBuffer,
4498     IDirect3DDevice8Impl_GetRasterStatus,
4499     IDirect3DDevice8Impl_SetGammaRamp,
4500     IDirect3DDevice8Impl_GetGammaRamp,
4501     IDirect3DDevice8Impl_CreateTexture,
4502     IDirect3DDevice8Impl_CreateVolumeTexture,
4503     IDirect3DDevice8Impl_CreateCubeTexture,
4504     IDirect3DDevice8Impl_CreateVertexBuffer,
4505     IDirect3DDevice8Impl_CreateIndexBuffer,
4506     IDirect3DDevice8Impl_CreateRenderTarget,
4507     IDirect3DDevice8Impl_CreateDepthStencilSurface,
4508     IDirect3DDevice8Impl_CreateImageSurface,
4509     IDirect3DDevice8Impl_CopyRects,
4510     IDirect3DDevice8Impl_UpdateTexture,
4511     IDirect3DDevice8Impl_GetFrontBuffer,
4512     IDirect3DDevice8Impl_SetRenderTarget,
4513     IDirect3DDevice8Impl_GetRenderTarget,
4514     IDirect3DDevice8Impl_GetDepthStencilSurface,
4515     IDirect3DDevice8Impl_BeginScene,
4516     IDirect3DDevice8Impl_EndScene,
4517     IDirect3DDevice8Impl_Clear,
4518     IDirect3DDevice8Impl_SetTransform,
4519     IDirect3DDevice8Impl_GetTransform,
4520     IDirect3DDevice8Impl_MultiplyTransform,
4521     IDirect3DDevice8Impl_SetViewport,
4522     IDirect3DDevice8Impl_GetViewport,
4523     IDirect3DDevice8Impl_SetMaterial,
4524     IDirect3DDevice8Impl_GetMaterial,
4525     IDirect3DDevice8Impl_SetLight,
4526     IDirect3DDevice8Impl_GetLight,
4527     IDirect3DDevice8Impl_LightEnable,
4528     IDirect3DDevice8Impl_GetLightEnable,
4529     IDirect3DDevice8Impl_SetClipPlane,
4530     IDirect3DDevice8Impl_GetClipPlane,
4531     IDirect3DDevice8Impl_SetRenderState,
4532     IDirect3DDevice8Impl_GetRenderState,
4533     IDirect3DDevice8Impl_BeginStateBlock,
4534     IDirect3DDevice8Impl_EndStateBlock,
4535     IDirect3DDevice8Impl_ApplyStateBlock,
4536     IDirect3DDevice8Impl_CaptureStateBlock,
4537     IDirect3DDevice8Impl_DeleteStateBlock,
4538     IDirect3DDevice8Impl_CreateStateBlock,
4539     IDirect3DDevice8Impl_SetClipStatus,
4540     IDirect3DDevice8Impl_GetClipStatus,
4541     IDirect3DDevice8Impl_GetTexture,
4542     IDirect3DDevice8Impl_SetTexture,
4543     IDirect3DDevice8Impl_GetTextureStageState,
4544     IDirect3DDevice8Impl_SetTextureStageState,
4545     IDirect3DDevice8Impl_ValidateDevice,
4546     IDirect3DDevice8Impl_GetInfo,
4547     IDirect3DDevice8Impl_SetPaletteEntries,
4548     IDirect3DDevice8Impl_GetPaletteEntries,
4549     IDirect3DDevice8Impl_SetCurrentTexturePalette,
4550     IDirect3DDevice8Impl_GetCurrentTexturePalette,
4551     IDirect3DDevice8Impl_DrawPrimitive,
4552     IDirect3DDevice8Impl_DrawIndexedPrimitive,
4553     IDirect3DDevice8Impl_DrawPrimitiveUP,
4554     IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4555     IDirect3DDevice8Impl_ProcessVertices,
4556     IDirect3DDevice8Impl_CreateVertexShader,
4557     IDirect3DDevice8Impl_SetVertexShader,
4558     IDirect3DDevice8Impl_GetVertexShader,
4559     IDirect3DDevice8Impl_DeleteVertexShader,
4560     IDirect3DDevice8Impl_SetVertexShaderConstant,
4561     IDirect3DDevice8Impl_GetVertexShaderConstant,
4562     IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4563     IDirect3DDevice8Impl_GetVertexShaderFunction,
4564     IDirect3DDevice8Impl_SetStreamSource,
4565     IDirect3DDevice8Impl_GetStreamSource,
4566     IDirect3DDevice8Impl_SetIndices,
4567     IDirect3DDevice8Impl_GetIndices,
4568     IDirect3DDevice8Impl_CreatePixelShader,
4569     IDirect3DDevice8Impl_SetPixelShader,
4570     IDirect3DDevice8Impl_GetPixelShader,
4571     IDirect3DDevice8Impl_DeletePixelShader,
4572     IDirect3DDevice8Impl_SetPixelShaderConstant,
4573     IDirect3DDevice8Impl_GetPixelShaderConstant,
4574     IDirect3DDevice8Impl_GetPixelShaderFunction,
4575     IDirect3DDevice8Impl_DrawRectPatch,
4576     IDirect3DDevice8Impl_DrawTriPatch,
4577     IDirect3DDevice8Impl_DeletePatch
4578 };