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