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