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