Restore the texture env mode on SetTexture - Fixes problem in
[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                     /* No need to walk through all mip-map levels, since already all assigned */
3182                     i = pTexture2->levels;
3183
3184                 } else {
3185                     if (i==0) {
3186
3187                         if (pTexture2->surfaces[i]->textureName == 0) {
3188                             glGenTextures(1, &pTexture2->surfaces[i]->textureName);
3189                             checkGLcall("glGenTextures");
3190                             TRACE("Texture %p (level %d) given name %d\n", pTexture2->surfaces[i], i, pTexture2->surfaces[i]->textureName);
3191                         }
3192
3193                         glBindTexture(GL_TEXTURE_2D, pTexture2->surfaces[i]->textureName);
3194                         checkGLcall("glBindTexture");
3195
3196                         TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", pTexture2->levels-1);   
3197                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1);
3198                         checkGLcall("glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels)");
3199
3200                     }
3201                     TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%lx, Mem=%p\n",
3202                           GL_TEXTURE_2D, i, fmt2glintFmt(pTexture2->format), pTexture2->surfaces[i]->myDesc.Width,
3203                           pTexture2->surfaces[i]->myDesc.Height, 0, fmt2glFmt(pTexture2->format),fmt2glType(pTexture2->format),
3204                           pTexture2->surfaces[i]->allocatedMemory);
3205                     glTexImage2D(GL_TEXTURE_2D, i,
3206                                  fmt2glintFmt(pTexture2->format),
3207                                  pTexture2->surfaces[i]->myDesc.Width,
3208                                  pTexture2->surfaces[i]->myDesc.Height,
3209                                  0,
3210                                  fmt2glFmt(pTexture2->format),
3211                                  fmt2glType(pTexture2->format),
3212                                  pTexture2->surfaces[i]->allocatedMemory
3213                                 );
3214                     checkGLcall("glTexImage2D");
3215
3216                     /* Removed glTexParameterf now TextureStageStates are initialized at startup */
3217                     pTexture2->Dirty = FALSE;
3218                 }
3219
3220             }
3221
3222         } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3223             IDirect3DVolumeTexture8Impl *pTexture2 = (IDirect3DVolumeTexture8Impl *) pTexture;
3224             int i;
3225
3226             /* Standard 3D (volume) texture */
3227             TRACE("Standard 3d texture\n");
3228             This->StateBlock.textureDimensions[Stage] = GL_TEXTURE_3D;
3229
3230             for (i=0; i<pTexture2->levels; i++) 
3231             {
3232
3233                 if (i==0 && pTexture2->volumes[i]->textureName != 0 && pTexture2->Dirty == FALSE) {
3234                     glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3235                     checkGLcall("glBindTexture");
3236                     TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3237
3238                     /* No need to walk through all mip-map levels, since already all assigned */
3239                     i = pTexture2->levels;
3240                 } else {
3241                     if (i==0) {
3242
3243                         if (pTexture2->volumes[i]->textureName == 0) {
3244                             glGenTextures(1, &pTexture2->volumes[i]->textureName);
3245                             checkGLcall("glGenTextures");
3246                             TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3247                         }
3248
3249                         glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3250                         checkGLcall("glBindTexture");
3251
3252                         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1); 
3253                         checkGLcall("glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1)");
3254                     }
3255
3256                     TRACE("Calling glTexImage3D %x i=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%lx, Mem=%p\n",
3257                           GL_TEXTURE_3D, i, fmt2glintFmt(pTexture2->format), pTexture2->volumes[i]->myDesc.Width,
3258                           pTexture2->volumes[i]->myDesc.Height, pTexture2->volumes[i]->myDesc.Depth,
3259                           0, fmt2glFmt(pTexture2->format),fmt2glType(pTexture2->format),
3260                           pTexture2->volumes[i]->allocatedMemory);
3261                     glTexImage3D(GL_TEXTURE_3D, i,
3262                                  fmt2glintFmt(pTexture2->format),
3263                                  pTexture2->volumes[i]->myDesc.Width,
3264                                  pTexture2->volumes[i]->myDesc.Height,
3265                                  pTexture2->volumes[i]->myDesc.Depth,
3266                                  0,
3267                                  fmt2glFmt(pTexture2->format),
3268                                  fmt2glType(pTexture2->format),
3269                                  pTexture2->volumes[i]->allocatedMemory
3270                                 );
3271                     checkGLcall("glTexImage3D");
3272
3273                     /* Removed glTexParameterf now TextureStageStates are initialized at startup */
3274                     pTexture2->Dirty = FALSE;
3275                 }
3276             }
3277
3278         } else {
3279             FIXME("(%p) : Incorrect type for a texture : %d\n", This, textureType);
3280         }
3281     } else {
3282         TRACE("Setting to no texture (ie default texture)\n");
3283         This->StateBlock.textureDimensions[Stage] = GL_TEXTURE_1D;
3284         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3285         checkGLcall("glBindTexture");
3286         TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3287     }
3288
3289     /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3290        a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3291     setupTextureStates (iface, Stage);
3292        
3293     return D3D_OK;
3294 }
3295
3296 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3297     ICOM_THIS(IDirect3DDevice8Impl,iface);
3298     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->StateBlock.texture_state[Stage][Type]);
3299     *pValue = This->StateBlock.texture_state[Stage][Type];
3300     return D3D_OK;
3301 }
3302
3303 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) {
3304     ICOM_THIS(IDirect3DDevice8Impl,iface);
3305
3306     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3307    
3308     TRACE("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value);
3309
3310     This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3311     This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3312     This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3313
3314     /* Handle recording of state blocks */
3315     if (This->isRecordingState) {
3316         TRACE("Recording... not performing anything\n");
3317         return D3D_OK;
3318     }
3319
3320     /* Make appropriate texture active */
3321     TRACE("Activating appropriate texture state %ld\n", Stage);
3322     if (This->isMultiTexture) {
3323         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3324         checkGLcall("glActiveTextureARB");
3325     } else if (Stage>0) {
3326         FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3327     }
3328
3329     switch (Type) {
3330
3331     case D3DTSS_MINFILTER             :
3332     case D3DTSS_MIPFILTER             :
3333         {
3334             DWORD ValueMIN = This->StateBlock.texture_state[Stage][D3DTSS_MINFILTER];
3335             DWORD ValueMIP = This->StateBlock.texture_state[Stage][D3DTSS_MIPFILTER];
3336             GLint realVal = GL_LINEAR;
3337
3338             if (ValueMIN == D3DTEXF_POINT) {
3339                 /* GL_NEAREST_* */
3340                 if (ValueMIP == D3DTEXF_POINT) {
3341                     realVal = GL_NEAREST_MIPMAP_NEAREST;
3342                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3343                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3344                 } else if (ValueMIP == D3DTEXF_NONE) {
3345                     realVal = GL_NEAREST;
3346                 } else {
3347                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3348                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3349                 }
3350             } else if (ValueMIN == D3DTEXF_LINEAR) {
3351                 /* GL_LINEAR_* */
3352                 if (ValueMIP == D3DTEXF_POINT) {
3353                     realVal = GL_LINEAR_MIPMAP_NEAREST;
3354                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3355                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3356                 } else if (ValueMIP == D3DTEXF_NONE) {
3357                     realVal = GL_LINEAR;
3358                 } else {
3359                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3360                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3361                 }
3362             } else if (ValueMIN == D3DTEXF_NONE) {
3363                 /* Doesnt really make sense - Windows just seems to disable
3364                    mipmapping when this occurs                              */
3365                 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3366                 realVal = GL_LINEAR;
3367
3368             } else {
3369                 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3370                 realVal = GL_LINEAR_MIPMAP_LINEAR;
3371             }
3372
3373             TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3374             glTexParameteri(This->StateBlock.textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3375             checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3376         }
3377         break;
3378
3379
3380     case D3DTSS_MAGFILTER             :
3381         if (Value == D3DTEXF_POINT) {
3382             glTexParameteri(This->StateBlock.textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3383             checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3384         } else if (Value == D3DTEXF_LINEAR) {
3385             glTexParameteri(This->StateBlock.textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3386             checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3387         } else {
3388             FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3389         }
3390         break;
3391
3392     case D3DTSS_COLORARG0             :
3393     case D3DTSS_ALPHAARG0             :
3394         /* FIXME: Mesa seems to struggle setting these at the moment */
3395         break;
3396
3397     case D3DTSS_COLORARG1             :
3398     case D3DTSS_COLORARG2             :
3399     case D3DTSS_ALPHAARG1             :
3400     case D3DTSS_ALPHAARG2             :
3401         {
3402             BOOL isAlphaReplicate = FALSE;
3403             BOOL isComplement     = FALSE;
3404             BOOL isAlphaArg       = (Type == D3DTSS_ALPHAARG1 || Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3405             int  operand= GL_SRC_COLOR;
3406             int  source = GL_TEXTURE;
3407
3408             /* Catch alpha replicate */
3409             if (Value & D3DTA_ALPHAREPLICATE) {
3410                 Value = Value & ~D3DTA_ALPHAREPLICATE;
3411                 isAlphaReplicate = TRUE;
3412             }
3413
3414             /* Catch Complement */
3415             if (Value & D3DTA_COMPLEMENT) {
3416                 Value = Value & ~D3DTA_COMPLEMENT;
3417                 isComplement = TRUE;
3418             }
3419
3420             /* Calculate the operand */
3421             if (isAlphaReplicate && !isComplement) {
3422                 operand = GL_SRC_ALPHA;
3423             } else if (isAlphaReplicate && isComplement) {
3424                 operand = GL_ONE_MINUS_SRC_ALPHA;
3425             } else if (isComplement) {
3426                 if (isAlphaArg) {
3427                     operand = GL_ONE_MINUS_SRC_COLOR;
3428                 } else {
3429                     operand = GL_ONE_MINUS_SRC_ALPHA;
3430                 }
3431             } else {
3432                 if (isAlphaArg) {
3433                     operand = GL_SRC_ALPHA;
3434                 } else {
3435                     operand = GL_SRC_COLOR;
3436                 }
3437             }
3438
3439             /* Calculate the source */
3440             switch (Value) {
3441             case D3DTA_CURRENT:   source  = GL_PREVIOUS_EXT;
3442                                   break;
3443             case D3DTA_DIFFUSE:   source  = GL_PRIMARY_COLOR_EXT;
3444                                   break;
3445             case D3DTA_TEXTURE:   source  = GL_TEXTURE;
3446                                   break;
3447             case D3DTA_TFACTOR:   source  = GL_CONSTANT_EXT;
3448                                   break;
3449
3450             /* According to the GL_ARB_texture_env_combine specs, SPECULAR is 'Secondary color' and
3451                isnt supported until base GL supports it
3452                There is no concept of temp registers as far as I can tell                          */
3453
3454             default:
3455                 FIXME("Unrecognized or unhandled texture arg %ld\n", Value);
3456             }
3457
3458             if (isAlphaArg) {
3459                 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_ALPHA_EXT(Type), source, OPERANDx_ALPHA_EXT(Type), operand);
3460                 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT(Type), source);
3461                 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT, source);");
3462                 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT(Type), operand);
3463                 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT, operand);");
3464             } else {
3465                 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_RGB_EXT(Type), source, OPERANDx_RGB_EXT(Type), operand);
3466                 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT(Type), source);
3467                 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT, source);");
3468                 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT(Type), operand);
3469                 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT, operand);");
3470             }
3471         }
3472         break;
3473
3474     case D3DTSS_ALPHAOP               :
3475     case D3DTSS_COLOROP               :
3476         {
3477
3478             int Scale = 1;
3479             int Parm = (Type == D3DTSS_ALPHAOP)? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
3480
3481             if (Type==D3DTSS_COLOROP && Value == D3DTOP_DISABLE) {
3482                 /* TODO: Disable by making this and all later levels disabled */
3483                 glDisable(GL_TEXTURE_1D);
3484                 checkGLcall("Disable GL_TEXTURE_1D");
3485                 glDisable(GL_TEXTURE_2D);
3486                 checkGLcall("Disable GL_TEXTURE_2D");
3487                 glDisable(GL_TEXTURE_3D);
3488                 checkGLcall("Disable GL_TEXTURE_3D");
3489             } else {
3490
3491                 /* Enable only the appropriate texture dimension */
3492                 if (Type==D3DTSS_COLOROP) {
3493                     if (This->StateBlock.textureDimensions[Stage] == GL_TEXTURE_1D) {
3494                         glEnable(GL_TEXTURE_1D);
3495                         checkGLcall("Enable GL_TEXTURE_1D");
3496                     } else {
3497                         glDisable(GL_TEXTURE_1D);
3498                         checkGLcall("Disable GL_TEXTURE_1D");
3499                     } 
3500                     if (This->StateBlock.textureDimensions[Stage] == GL_TEXTURE_2D) {
3501                         glEnable(GL_TEXTURE_2D);
3502                         checkGLcall("Enable GL_TEXTURE_2D");
3503                     } else {
3504                         glDisable(GL_TEXTURE_2D);
3505                         checkGLcall("Disable GL_TEXTURE_2D");
3506                     }
3507                     if (This->StateBlock.textureDimensions[Stage] == GL_TEXTURE_3D) {
3508                         glEnable(GL_TEXTURE_3D);
3509                         checkGLcall("Enable GL_TEXTURE_3D");
3510                     } else {
3511                         glDisable(GL_TEXTURE_3D);
3512                         checkGLcall("Disable GL_TEXTURE_3D");
3513                     }
3514                 }
3515
3516                 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
3517                 if (Value != D3DTOP_DISABLE) {
3518                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
3519                 }
3520
3521                 /* Now set up the operand correctly */
3522                 switch (Value) {
3523                 case D3DTOP_DISABLE                   :
3524                     /* Contrary to the docs, alpha can be disabled when colorop is enabled
3525                        and it works, so ignore this op */
3526                     TRACE("Disable ALPHAOP but COLOROP enabled!\n");
3527                     break;
3528
3529                 case D3DTOP_SELECTARG1                :
3530                     glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
3531                     checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
3532                     break;
3533
3534                 case D3DTOP_MODULATE4X                : Scale = Scale * 2;  /* Drop through */
3535                 case D3DTOP_MODULATE2X                : Scale = Scale * 2;  /* Drop through */
3536                 case D3DTOP_MODULATE                  :
3537
3538                     /* Correct scale */
3539                     if (Type == D3DTSS_ALPHAOP) {
3540                         glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale);
3541                         checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale)");
3542                     } else {
3543                         glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale);
3544                         checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale)");
3545                     }
3546                     glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);
3547                     checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);");
3548                     break;
3549
3550                 case D3DTOP_ADD                       :
3551                     glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD);
3552                     checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD)");
3553                     break;
3554
3555                 case D3DTOP_ADDSIGNED2X               : Scale = Scale * 2;  /* Drop through */
3556                 case D3DTOP_ADDSIGNED                 :
3557                     glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT);
3558                     checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT)");
3559                     break;
3560
3561                 case D3DTOP_DOTPRODUCT3               :
3562                     /*glTexEnvi(GL_TEXTURE_ENV, Parm, GL_DOT3_RGBA);
3563                     checkGLcall("glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA);");
3564                     break;*/
3565
3566                 case D3DTOP_SUBTRACT                  :
3567                     /* glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT); Missing? */
3568                 case D3DTOP_SELECTARG2                :
3569                     /* GL_REPLACE, swap args 0 and 1? */
3570                 case D3DTOP_ADDSMOOTH                 :
3571                 case D3DTOP_BLENDDIFFUSEALPHA         :
3572                 case D3DTOP_BLENDTEXTUREALPHA         :
3573                 case D3DTOP_BLENDFACTORALPHA          :
3574                 case D3DTOP_BLENDTEXTUREALPHAPM       :
3575                 case D3DTOP_BLENDCURRENTALPHA         :
3576                 case D3DTOP_PREMODULATE               :
3577                 case D3DTOP_MODULATEALPHA_ADDCOLOR    :
3578                 case D3DTOP_MODULATECOLOR_ADDALPHA    :
3579                 case D3DTOP_MODULATEINVALPHA_ADDCOLOR :
3580                 case D3DTOP_MODULATEINVCOLOR_ADDALPHA :
3581                 case D3DTOP_BUMPENVMAP                :
3582                 case D3DTOP_BUMPENVMAPLUMINANCE       :
3583                 case D3DTOP_MULTIPLYADD               :
3584                 case D3DTOP_LERP                      :
3585                 default:
3586                     FIXME("Unhandled texture operation %ld\n", Value);
3587                 }
3588             }
3589             break;
3590         }
3591
3592     case D3DTSS_ADDRESSU              :
3593     case D3DTSS_ADDRESSV              :
3594     case D3DTSS_ADDRESSW              :
3595         {
3596             GLint wrapParm = GL_REPEAT;
3597             switch (Value) {
3598             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
3599             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP; break;      
3600             case D3DTADDRESS_BORDER: wrapParm = GL_CLAMP_TO_EDGE; break;      
3601
3602             case D3DTADDRESS_MIRROR:      /* Unsupported in OpenGL? */
3603             case D3DTADDRESS_MIRRORONCE:  /* Unsupported in OpenGL? */
3604             default:
3605                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3606                 wrapParm = GL_REPEAT; 
3607             }
3608
3609             switch (Type) {
3610             case D3DTSS_ADDRESSU:
3611                 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock.textureDimensions[Stage]);
3612                 glTexParameteri(This->StateBlock.textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3613                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3614                 break;
3615             case D3DTSS_ADDRESSV:
3616                 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock.textureDimensions[Stage]);
3617                 glTexParameteri(This->StateBlock.textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3618                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3619                 break;
3620             case D3DTSS_ADDRESSW:
3621                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock.textureDimensions[Stage]);
3622                 glTexParameteri(This->StateBlock.textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3623                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3624                 break;
3625             default: /* nop */
3626                 break; /** stupic compilator */
3627             }
3628         }
3629         break;
3630
3631     case D3DTSS_BORDERCOLOR           :
3632         {
3633             float col[4];
3634             col[0] = ((Value >> 16) & 0xFF) / 255.0;
3635             col[1] = ((Value >>  8) & 0xFF) / 255.0;
3636             col[2] = ((Value >>  0) & 0xFF) / 255.0;
3637             col[3] = ((Value >> 24) & 0xFF) / 255.0;
3638
3639             TRACE("Setting border color for %x to %lx\n", This->StateBlock.textureDimensions[Stage], Value); 
3640             glTexParameterfv(This->StateBlock.textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3641             checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3642         }
3643         break;
3644
3645         /* Unhandled */
3646     case D3DTSS_BUMPENVMAT00          :
3647     case D3DTSS_BUMPENVMAT01          :
3648     case D3DTSS_BUMPENVMAT10          :
3649     case D3DTSS_BUMPENVMAT11          :
3650     case D3DTSS_TEXCOORDINDEX         :
3651     case D3DTSS_MIPMAPLODBIAS         :
3652     case D3DTSS_MAXMIPLEVEL           :
3653     case D3DTSS_MAXANISOTROPY         :
3654     case D3DTSS_BUMPENVLSCALE         :
3655     case D3DTSS_BUMPENVLOFFSET        :
3656     case D3DTSS_TEXTURETRANSFORMFLAGS :
3657     case D3DTSS_RESULTARG             :
3658     default:
3659         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3660         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3661     }
3662     return D3D_OK;
3663 }
3664 HRESULT  WINAPI  IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3665     ICOM_THIS(IDirect3DDevice8Impl,iface);
3666     FIXME("(%p) : stub\n", This);    return D3D_OK;
3667 }
3668 HRESULT  WINAPI  IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID,void* pDevInfoStruct,DWORD DevInfoStructSize) {
3669     ICOM_THIS(IDirect3DDevice8Impl,iface);
3670     FIXME("(%p) : stub\n", This);    return D3D_OK;
3671 }
3672 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,CONST PALETTEENTRY* pEntries) {
3673     ICOM_THIS(IDirect3DDevice8Impl,iface);
3674     FIXME("(%p) : stub\n", This);    return D3D_OK;
3675 }
3676 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,PALETTEENTRY* pEntries) {
3677     ICOM_THIS(IDirect3DDevice8Impl,iface);
3678     FIXME("(%p) : stub\n", This);    return D3D_OK;
3679 }
3680 HRESULT  WINAPI  IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3681     ICOM_THIS(IDirect3DDevice8Impl,iface);
3682     FIXME("(%p) : stub\n", This);    return D3D_OK;
3683 }
3684 HRESULT  WINAPI  IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3685     ICOM_THIS(IDirect3DDevice8Impl,iface);
3686     FIXME("(%p) : stub\n", This);    return D3D_OK;
3687 }
3688 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) {
3689
3690     IDirect3DVertexBuffer8     *pVB;
3691
3692     ICOM_THIS(IDirect3DDevice8Impl,iface);
3693     pVB = This->StateBlock.stream_source[0];
3694
3695     TRACE("(%p) : Type=%d, Start=%d, Count=%d\n", This, PrimitiveType, StartVertex, PrimitiveCount);
3696
3697     DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE,
3698                    This->StateBlock.VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory, StartVertex, -1, 0, NULL, 0);
3699
3700     return D3D_OK;
3701 }
3702 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3703                                                            UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3704     UINT idxStride = 2;
3705     IDirect3DIndexBuffer8      *pIB;
3706     IDirect3DVertexBuffer8     *pVB;
3707     D3DINDEXBUFFER_DESC         IdxBufDsc;
3708
3709     ICOM_THIS(IDirect3DDevice8Impl,iface);
3710     pIB = This->StateBlock.pIndexData;
3711     pVB = This->StateBlock.stream_source[0];
3712
3713     TRACE("(%p) : Type=%d, min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, PrimitiveType,
3714           minIndex, NumVertices, startIndex, primCount);
3715
3716     IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3717     if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3718         idxStride = 2;
3719     } else {
3720         idxStride = 4;
3721     }
3722
3723     DrawPrimitiveI(iface, PrimitiveType, primCount, TRUE, This->StateBlock.VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory,
3724                    This->StateBlock.baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3725                    minIndex);
3726
3727     return D3D_OK;
3728 }
3729 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3730     ICOM_THIS(IDirect3DDevice8Impl,iface);
3731
3732     TRACE("(%p) : Type=%d, pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3733
3734     if (This->StateBlock.stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock.stream_source[0]);
3735
3736     This->StateBlock.stream_source[0] = NULL;
3737     This->StateBlock.stream_stride[0] = VertexStreamZeroStride;
3738     DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE, This->StateBlock.VertexShader, pVertexStreamZeroData,
3739                    0, 0, 0, NULL, 0);
3740     This->StateBlock.stream_stride[0] = 0;
3741
3742     /*stream zero settings set to null at end */
3743     return D3D_OK;
3744 }
3745 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3746                                                              UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3747                                                              D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3748                                                              UINT VertexStreamZeroStride) {
3749     int idxStride;
3750     ICOM_THIS(IDirect3DDevice8Impl,iface);
3751     TRACE("(%p) : Type=%d, MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType,
3752           MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,  IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3753
3754     if (This->StateBlock.stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock.stream_source[0]);
3755     if (IndexDataFormat == D3DFMT_INDEX16) {
3756         idxStride = 2;
3757     } else {
3758         idxStride = 4;
3759     }
3760
3761     This->StateBlock.stream_source[0] = NULL;
3762     This->StateBlock.stream_stride[0] = VertexStreamZeroStride;
3763     DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, TRUE, This->StateBlock.VertexShader, pVertexStreamZeroData,
3764                    This->StateBlock.baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3765
3766     /*stream zero settings set to null at end */
3767     This->StateBlock.stream_stride[0] = 0;
3768     IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3769
3770     return D3D_OK;
3771 }
3772 HRESULT  WINAPI  IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3773     ICOM_THIS(IDirect3DDevice8Impl,iface);
3774     FIXME("(%p) : stub\n", This);    return D3D_OK;
3775 }
3776 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3777     ICOM_THIS(IDirect3DDevice8Impl,iface);
3778     VERTEXSHADER8* object;
3779     UINT i;
3780
3781     TRACE("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p\n", This, pDeclaration, pFunction);    
3782     if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3783       return D3DERR_INVALIDCALL;
3784     }
3785     for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(VERTEXSHADER8*); ++i) ;
3786     if (i >= sizeof(VertexShaders) / sizeof(VERTEXSHADER8*)) {
3787       return D3DERR_OUTOFVIDEOMEMORY;
3788     }
3789     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VERTEXSHADER8));
3790     if (NULL == object) {
3791       return D3DERR_OUTOFVIDEOMEMORY;
3792     }
3793
3794     object->usage = Usage;
3795     object->data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SHADERDATA8));
3796
3797     VertexShaders[i] = object;
3798     *pHandle = VS_HIGHESTFIXEDFXF + i;
3799
3800     object->decl = (DWORD*) pDeclaration;
3801     object->function = (DWORD*) pFunction;
3802
3803     vshader_decl_parse(object);
3804     vshader_program_parse(object);
3805
3806     /* copy the function ... because it will certainly be released by application */
3807     if (NULL != pFunction) {
3808       object->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->functionLength);
3809       memcpy(object->function, pFunction, object->functionLength);
3810     }
3811     /* copy the declaration too */
3812     object->decl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->declLength);
3813     memcpy(object->decl, pDeclaration, object->declLength);
3814     return D3D_OK;
3815 }
3816 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3817     ICOM_THIS(IDirect3DDevice8Impl,iface);
3818
3819     This->UpdateStateBlock->VertexShader = Handle;
3820     This->UpdateStateBlock->Changed.vertexShader = TRUE;
3821     This->UpdateStateBlock->Set.vertexShader = TRUE;
3822
3823     /* Handle recording of state blocks */
3824     if (This->isRecordingState) {
3825         TRACE("Recording... not performing anything\n");
3826         return D3D_OK;
3827     }
3828     if (Handle <= VS_HIGHESTFIXEDFXF) {
3829         TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3830         return D3D_OK;
3831     } else {
3832         FIXME("(%p) : Created shader, Handle=%lx stub\n", This, Handle);
3833         return D3D_OK;
3834     }
3835 }
3836 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3837     ICOM_THIS(IDirect3DDevice8Impl,iface);
3838     TRACE("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock.VertexShader);
3839     *pHandle = This->StateBlock.VertexShader;
3840     return D3D_OK;
3841 }
3842
3843 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3844     ICOM_THIS(IDirect3DDevice8Impl,iface);
3845     VERTEXSHADER8* object;
3846
3847     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3848       return D3DERR_INVALIDCALL;
3849     }
3850     object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3851     if (NULL == object) {
3852       return D3DERR_INVALIDCALL;
3853     }
3854     TRACE("(%p) : freing VertexShader %p\n", This, object);
3855     /* TODO: check validity of object */
3856     if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3857     HeapFree(GetProcessHeap(), 0, (void *)object->decl);
3858     HeapFree(GetProcessHeap(), 0, (void *)object->data);
3859     HeapFree(GetProcessHeap(), 0, (void *)object);
3860     VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3861     return D3D_OK;
3862 }
3863
3864 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3865   ICOM_THIS(IDirect3DDevice8Impl,iface);
3866   VERTEXSHADER8* object;
3867   DWORD Handle = This->UpdateStateBlock->VertexShader;
3868
3869   /* FIXME("(%p) : VertexShader_SetConstant not fully supported yet\n", This); */
3870   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3871     return D3DERR_INVALIDCALL;
3872   }
3873   object = VERTEX_SHADER(Handle);
3874   if (NULL == object || NULL == pConstantData) {
3875     return D3DERR_INVALIDCALL;
3876   }
3877   if (NULL == object->data) { /* temporary while datas not supported */
3878     FIXME("(%p) : VertexShader_SetConstant not fully supported yet\n", This);
3879     return D3DERR_INVALIDCALL;
3880   }
3881   memcpy(object->data->C + Register, pConstantData, ConstantCount * sizeof(D3DSHADERVECTOR));
3882
3883   return D3D_OK;
3884 }
3885 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3886   ICOM_THIS(IDirect3DDevice8Impl,iface);
3887   VERTEXSHADER8* object;
3888   DWORD Handle = This->UpdateStateBlock->VertexShader;
3889
3890   FIXME("(%p) : VertexShader_GetConstant not fully supported yet\n", This);
3891
3892   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3893     return D3DERR_INVALIDCALL;
3894   }
3895   object = VERTEX_SHADER(Handle);
3896   if (NULL == object || NULL == pConstantData) {
3897     return D3DERR_INVALIDCALL;
3898   }
3899   if (NULL == object->data) { /* temporary while datas not supported */
3900     return D3DERR_INVALIDCALL;
3901   }
3902   memcpy(pConstantData, object->data->C + Register, ConstantCount * sizeof(D3DSHADERVECTOR));
3903
3904   return D3D_OK;
3905 }
3906 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3907     ICOM_THIS(IDirect3DDevice8Impl,iface);
3908     VERTEXSHADER8* object;
3909
3910     object = VERTEX_SHADER(Handle);
3911     if (NULL == object) {
3912       return D3DERR_INVALIDCALL;
3913     }
3914     if (NULL == pData) {
3915       *pSizeOfData = object->declLength;
3916       return D3D_OK;
3917     }
3918     if (*pSizeOfData < object->declLength) {
3919       *pSizeOfData = object->declLength;
3920       return D3DERR_MOREDATA;
3921     }
3922     TRACE("(%p) : GetVertexShaderDeclaration copying to %p\n", This, pData);
3923     memcpy(pData, object->decl, object->declLength);
3924     return D3D_OK;
3925 }
3926 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3927     ICOM_THIS(IDirect3DDevice8Impl,iface);
3928     VERTEXSHADER8* object;
3929
3930     object = VERTEX_SHADER(Handle);
3931     if (NULL == object) {
3932       return D3DERR_INVALIDCALL;
3933     }
3934     if (NULL == pData) {
3935       *pSizeOfData = object->functionLength;
3936       return D3D_OK;
3937     }
3938     if (*pSizeOfData < object->functionLength) {
3939       *pSizeOfData = object->functionLength;
3940       return D3DERR_MOREDATA;
3941     }
3942     if (NULL == object->function) { /* no function defined */
3943       TRACE("(%p) : GetVertexShaderFunction no User Function defined using NULL to %p\n", This, pData);
3944       ((DWORD *) pData) = NULL;
3945     } else {
3946       TRACE("(%p) : GetVertexShaderFunction copying to %p\n", This, pData);
3947       memcpy(pData, object->function, object->functionLength);
3948     }
3949     return D3D_OK;
3950 }
3951
3952 HRESULT  WINAPI  IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData,UINT BaseVertexIndex) {
3953     ICOM_THIS(IDirect3DDevice8Impl,iface);
3954     IDirect3DIndexBuffer8 *oldIdxs;
3955
3956     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3957     oldIdxs = This->StateBlock.pIndexData;
3958
3959     This->UpdateStateBlock->Changed.Indices = TRUE;
3960     This->UpdateStateBlock->Set.Indices = TRUE;
3961     This->UpdateStateBlock->pIndexData = pIndexData;
3962     This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3963
3964     /* Handle recording of state blocks */
3965     if (This->isRecordingState) {
3966         TRACE("Recording... not performing anything\n");
3967         return D3D_OK;
3968     }
3969
3970     if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3971     if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock.pIndexData);
3972     return D3D_OK;
3973 }
3974 HRESULT  WINAPI  IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3975     ICOM_THIS(IDirect3DDevice8Impl,iface);
3976     FIXME("(%p) : stub\n", This);
3977
3978     *ppIndexData = This->StateBlock.pIndexData;
3979     /* up ref count on ppindexdata */
3980     if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3981     *pBaseVertexIndex = This->StateBlock.baseVertexIndex;
3982
3983     return D3D_OK;
3984 }
3985 HRESULT  WINAPI  IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3986     ICOM_THIS(IDirect3DDevice8Impl,iface);
3987     PIXELSHADER8* object;
3988     UINT i;
3989
3990     FIXME("(%p) : PixelShader not fully supported yet\n", This);    
3991     if (NULL == pFunction || NULL == pHandle) {
3992       return D3DERR_INVALIDCALL;
3993     }
3994     for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(PIXELSHADER8*); ++i) ;
3995     if (i >= sizeof(PixelShaders) / sizeof(PIXELSHADER8*)) {
3996       return D3DERR_OUTOFVIDEOMEMORY;
3997     }
3998     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PIXELSHADER8));
3999     if (NULL == object) {
4000       return D3DERR_OUTOFVIDEOMEMORY;
4001     }
4002     
4003     object->data = NULL; /* TODO */
4004
4005     PixelShaders[i] = object;
4006     *pHandle = VS_HIGHESTFIXEDFXF + i;
4007
4008     object->function = pFunction;
4009     for (i = 0; 0xFFFFFFFF != pFunction[i]; ++i) ;
4010     object->functionLength = i + 1;
4011
4012     return D3D_OK;
4013 }
4014 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4015     ICOM_THIS(IDirect3DDevice8Impl,iface);
4016
4017     This->UpdateStateBlock->PixelShader = Handle;
4018     This->UpdateStateBlock->Changed.pixelShader = TRUE;
4019     This->UpdateStateBlock->Set.pixelShader = TRUE;
4020
4021     /* Handle recording of state blocks */
4022     if (This->isRecordingState) {
4023         TRACE("Recording... not performing anything\n");
4024         return D3D_OK;
4025     }
4026
4027     /* FIXME: Quieten when not being used */
4028     if (Handle != 0) {
4029       FIXME("(%p) : stub %ld\n", This, Handle);
4030     } else {
4031       TRACE("(%p) : stub %ld\n", This, Handle);
4032     }
4033
4034     return D3D_OK;
4035 }
4036 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4037     ICOM_THIS(IDirect3DDevice8Impl,iface);
4038     TRACE("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock.PixelShader);
4039     *pHandle = This->StateBlock.PixelShader;
4040     return D3D_OK;
4041 }
4042
4043 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4044     ICOM_THIS(IDirect3DDevice8Impl,iface);
4045     PIXELSHADER8* object;   
4046
4047     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4048       return D3DERR_INVALIDCALL;
4049     }
4050     object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4051     TRACE("(%p) : freeing PixelShader %p\n", This, object);
4052     /* TODO: check validity of object before free */
4053     HeapFree(GetProcessHeap(), 0, (void *)object);
4054     PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = 0;
4055     return D3D_OK;
4056 }
4057 #define PIXEL_SHADER(Handle) ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(PixelShaders) / sizeof(PIXELSHADER8*)) ? NULL : PixelShaders[Handle]) : PixelShaders[Handle - VS_HIGHESTFIXEDFXF])
4058
4059 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,CONST void* pConstantData, DWORD ConstantCount) {
4060     ICOM_THIS(IDirect3DDevice8Impl,iface);
4061     FIXME("(%p) : stub\n", This);
4062     return D3D_OK;
4063 }
4064 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,void* pConstantData, DWORD ConstantCount) {
4065     ICOM_THIS(IDirect3DDevice8Impl,iface);
4066     FIXME("(%p) : stub\n", This);  
4067     return D3D_OK;
4068 }
4069 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4070     ICOM_THIS(IDirect3DDevice8Impl,iface);
4071     PIXELSHADER8* object;
4072
4073     object = PIXEL_SHADER(Handle);
4074     if (NULL == object) {
4075       return D3DERR_INVALIDCALL;
4076     }
4077     if (NULL == pData) {
4078       *pSizeOfData = object->functionLength;
4079       return D3D_OK;
4080     }
4081     if (*pSizeOfData < object->functionLength) {
4082       *pSizeOfData = object->functionLength;
4083       return D3DERR_MOREDATA;
4084     }
4085     TRACE("(%p) : GetPixelShaderFunction copying to %p\n", This, pData);
4086     memcpy(pData, object->function, object->functionLength);
4087     return D3D_OK;
4088 }
4089 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4090     ICOM_THIS(IDirect3DDevice8Impl,iface);
4091     FIXME("(%p) : stub\n", This);    return D3D_OK;
4092 }
4093 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4094     ICOM_THIS(IDirect3DDevice8Impl,iface);
4095     FIXME("(%p) : stub\n", This);    return D3D_OK;
4096 }
4097 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4098     ICOM_THIS(IDirect3DDevice8Impl,iface);
4099     FIXME("(%p) : stub\n", This);    return D3D_OK;
4100 }
4101
4102 HRESULT  WINAPI  IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4103     IDirect3DVertexBuffer8 *oldSrc;
4104     ICOM_THIS(IDirect3DDevice8Impl,iface);
4105
4106     oldSrc = This->StateBlock.stream_source[StreamNumber];
4107     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4108
4109     This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4110     This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4111     This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4112     This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4113
4114     /* Handle recording of state blocks */
4115     if (This->isRecordingState) {
4116         TRACE("Recording... not performing anything\n");
4117         return D3D_OK;
4118     }
4119
4120     if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4121     if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4122     return D3D_OK;
4123 }
4124 HRESULT  WINAPI  IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4125     ICOM_THIS(IDirect3DDevice8Impl,iface);
4126     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock.stream_source[StreamNumber], This->StateBlock.stream_stride[StreamNumber]);
4127     *pStream = This->StateBlock.stream_source[StreamNumber];
4128     *pStride = This->StateBlock.stream_stride[StreamNumber];
4129     IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4130     return D3D_OK;
4131 }
4132
4133
4134 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4135 {
4136     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4137     IDirect3DDevice8Impl_QueryInterface,
4138     IDirect3DDevice8Impl_AddRef,
4139     IDirect3DDevice8Impl_Release,
4140     IDirect3DDevice8Impl_TestCooperativeLevel,
4141     IDirect3DDevice8Impl_GetAvailableTextureMem,
4142     IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4143     IDirect3DDevice8Impl_GetDirect3D,
4144     IDirect3DDevice8Impl_GetDeviceCaps,
4145     IDirect3DDevice8Impl_GetDisplayMode,
4146     IDirect3DDevice8Impl_GetCreationParameters,
4147     IDirect3DDevice8Impl_SetCursorProperties,
4148     IDirect3DDevice8Impl_SetCursorPosition,
4149     IDirect3DDevice8Impl_ShowCursor,
4150     IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4151     IDirect3DDevice8Impl_Reset,
4152     IDirect3DDevice8Impl_Present,
4153     IDirect3DDevice8Impl_GetBackBuffer,
4154     IDirect3DDevice8Impl_GetRasterStatus,
4155     IDirect3DDevice8Impl_SetGammaRamp,
4156     IDirect3DDevice8Impl_GetGammaRamp,
4157     IDirect3DDevice8Impl_CreateTexture,
4158     IDirect3DDevice8Impl_CreateVolumeTexture,
4159     IDirect3DDevice8Impl_CreateCubeTexture,
4160     IDirect3DDevice8Impl_CreateVertexBuffer,
4161     IDirect3DDevice8Impl_CreateIndexBuffer,
4162     IDirect3DDevice8Impl_CreateRenderTarget,
4163     IDirect3DDevice8Impl_CreateDepthStencilSurface,
4164     IDirect3DDevice8Impl_CreateImageSurface,
4165     IDirect3DDevice8Impl_CopyRects,
4166     IDirect3DDevice8Impl_UpdateTexture,
4167     IDirect3DDevice8Impl_GetFrontBuffer,
4168     IDirect3DDevice8Impl_SetRenderTarget,
4169     IDirect3DDevice8Impl_GetRenderTarget,
4170     IDirect3DDevice8Impl_GetDepthStencilSurface,
4171     IDirect3DDevice8Impl_BeginScene,
4172     IDirect3DDevice8Impl_EndScene,
4173     IDirect3DDevice8Impl_Clear,
4174     IDirect3DDevice8Impl_SetTransform,
4175     IDirect3DDevice8Impl_GetTransform,
4176     IDirect3DDevice8Impl_MultiplyTransform,
4177     IDirect3DDevice8Impl_SetViewport,
4178     IDirect3DDevice8Impl_GetViewport,
4179     IDirect3DDevice8Impl_SetMaterial,
4180     IDirect3DDevice8Impl_GetMaterial,
4181     IDirect3DDevice8Impl_SetLight,
4182     IDirect3DDevice8Impl_GetLight,
4183     IDirect3DDevice8Impl_LightEnable,
4184     IDirect3DDevice8Impl_GetLightEnable,
4185     IDirect3DDevice8Impl_SetClipPlane,
4186     IDirect3DDevice8Impl_GetClipPlane,
4187     IDirect3DDevice8Impl_SetRenderState,
4188     IDirect3DDevice8Impl_GetRenderState,
4189     IDirect3DDevice8Impl_BeginStateBlock,
4190     IDirect3DDevice8Impl_EndStateBlock,
4191     IDirect3DDevice8Impl_ApplyStateBlock,
4192     IDirect3DDevice8Impl_CaptureStateBlock,
4193     IDirect3DDevice8Impl_DeleteStateBlock,
4194     IDirect3DDevice8Impl_CreateStateBlock,
4195     IDirect3DDevice8Impl_SetClipStatus,
4196     IDirect3DDevice8Impl_GetClipStatus,
4197     IDirect3DDevice8Impl_GetTexture,
4198     IDirect3DDevice8Impl_SetTexture,
4199     IDirect3DDevice8Impl_GetTextureStageState,
4200     IDirect3DDevice8Impl_SetTextureStageState,
4201     IDirect3DDevice8Impl_ValidateDevice,
4202     IDirect3DDevice8Impl_GetInfo,
4203     IDirect3DDevice8Impl_SetPaletteEntries,
4204     IDirect3DDevice8Impl_GetPaletteEntries,
4205     IDirect3DDevice8Impl_SetCurrentTexturePalette,
4206     IDirect3DDevice8Impl_GetCurrentTexturePalette,
4207     IDirect3DDevice8Impl_DrawPrimitive,
4208     IDirect3DDevice8Impl_DrawIndexedPrimitive,
4209     IDirect3DDevice8Impl_DrawPrimitiveUP,
4210     IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4211     IDirect3DDevice8Impl_ProcessVertices,
4212     IDirect3DDevice8Impl_CreateVertexShader,
4213     IDirect3DDevice8Impl_SetVertexShader,
4214     IDirect3DDevice8Impl_GetVertexShader,
4215     IDirect3DDevice8Impl_DeleteVertexShader,
4216     IDirect3DDevice8Impl_SetVertexShaderConstant,
4217     IDirect3DDevice8Impl_GetVertexShaderConstant,
4218     IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4219     IDirect3DDevice8Impl_GetVertexShaderFunction,
4220     IDirect3DDevice8Impl_SetStreamSource,
4221     IDirect3DDevice8Impl_GetStreamSource,
4222     IDirect3DDevice8Impl_SetIndices,
4223     IDirect3DDevice8Impl_GetIndices,
4224     IDirect3DDevice8Impl_CreatePixelShader,
4225     IDirect3DDevice8Impl_SetPixelShader,
4226     IDirect3DDevice8Impl_GetPixelShader,
4227     IDirect3DDevice8Impl_DeletePixelShader,
4228     IDirect3DDevice8Impl_SetPixelShaderConstant,
4229     IDirect3DDevice8Impl_GetPixelShaderConstant,
4230     IDirect3DDevice8Impl_GetPixelShaderFunction,
4231     IDirect3DDevice8Impl_DrawRectPatch,
4232     IDirect3DDevice8Impl_DrawTriPatch,
4233     IDirect3DDevice8Impl_DeletePatch
4234 };
4235
4236 void CreateStateBlock(LPDIRECT3DDEVICE8 iface) {
4237     D3DLINEPATTERN lp;
4238     int i;
4239
4240     ICOM_THIS(IDirect3DDevice8Impl,iface);
4241
4242     /* Note this may have a large overhead but it should only be executed
4243        once, in order to initialize the complete state of the device and 
4244        all opengl equivalents                                            */
4245     TRACE("-----------------------> Setting up device defaults...\n");
4246     This->StateBlock.blockType = D3DSBT_ALL;
4247
4248     /* FIXME: Set some of the defaults for lights, transforms etc */
4249     memcpy(&This->StateBlock.transforms[D3DTS_PROJECTION], &idmatrix, sizeof(idmatrix));
4250     memcpy(&This->StateBlock.transforms[D3DTS_VIEW], &idmatrix, sizeof(idmatrix));
4251     for (i = 0; i < 256; ++i) {
4252       memcpy(&This->StateBlock.transforms[D3DTS_WORLDMATRIX(i)], &idmatrix, sizeof(idmatrix));
4253     }
4254  
4255     /* Render states: */
4256     if (This->PresentParms.EnableAutoDepthStencil) {
4257        IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZENABLE, D3DZB_TRUE );
4258     } else {
4259        IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZENABLE, D3DZB_FALSE );
4260     }
4261     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FILLMODE, D3DFILL_SOLID);
4262     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
4263     lp.wRepeatFactor = 0; lp.wLinePattern = 0; IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_LINEPATTERN, (DWORD) &lp);
4264     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZWRITEENABLE, TRUE);
4265     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ALPHATESTENABLE, FALSE);
4266     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_LASTPIXEL, TRUE);
4267     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_SRCBLEND, D3DBLEND_ONE);
4268     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_DESTBLEND, D3DBLEND_ZERO);
4269     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_CULLMODE, D3DCULL_CCW);
4270     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
4271     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
4272     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ALPHAREF, 0xff); /*??*/
4273     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_DITHERENABLE, FALSE);
4274     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ALPHABLENDENABLE, FALSE);
4275     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGENABLE, FALSE);
4276     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_SPECULARENABLE, FALSE);
4277     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZVISIBLE, 0);
4278     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGCOLOR, 0);
4279     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
4280     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGSTART, 0.0f);
4281     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGEND, 1.0f);
4282     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGDENSITY, 1.0f);
4283     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_EDGEANTIALIAS, FALSE);
4284     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_ZBIAS, 0);
4285     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_RANGEFOGENABLE, FALSE);
4286     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILENABLE, FALSE);
4287     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
4288     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
4289     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
4290     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
4291     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILREF, 0);
4292     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILMASK, 0xFFFFFFFF);
4293     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
4294     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
4295     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP0, 0);
4296     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP1, 0);
4297     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP2, 0);
4298     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP3, 0);
4299     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP4, 0);
4300     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP5, 0);
4301     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP6, 0);
4302     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_WRAP7, 0);
4303     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_CLIPPING, TRUE);
4304     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_LIGHTING, TRUE);
4305     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_AMBIENT, 0);
4306     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
4307     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_COLORVERTEX, TRUE);
4308     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_LOCALVIEWER, TRUE);
4309     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_NORMALIZENORMALS, FALSE);
4310     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
4311     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
4312     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR2);
4313     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
4314     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
4315     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_CLIPPLANEENABLE, 0);
4316     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
4317     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSIZE, 1.0f);
4318     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSIZE_MIN, 0.0f);
4319     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSPRITEENABLE, FALSE);
4320     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSCALEENABLE, FALSE);
4321     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSCALE_A, TRUE);
4322     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSCALE_B, TRUE);
4323     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSCALE_C, TRUE);
4324     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_MULTISAMPLEANTIALIAS, TRUE);
4325     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
4326     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
4327     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_PATCHSEGMENTS, 1.0f);
4328     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_DEBUGMONITORTOKEN, D3DDMT_DISABLE);
4329     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POINTSIZE_MAX, (DWORD) 64.0f);
4330     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
4331     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_COLORWRITEENABLE, 0x0000000F);
4332     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_TWEENFACTOR, (DWORD) 0.0f);
4333     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_BLENDOP, D3DBLENDOP_ADD);
4334     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_POSITIONORDER, D3DORDER_CUBIC);
4335     IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_NORMALORDER, D3DORDER_LINEAR);
4336
4337     /* Texture Stage States - Put directly into state block, we will call function below */
4338     for (i=0; i<This->TextureUnits;i++) {
4339         memcpy(&This->StateBlock.transforms[D3DTS_TEXTURE0+i], &idmatrix, sizeof(idmatrix));
4340         This->StateBlock.texture_state[i][D3DTSS_COLOROP               ] = (i==0)? D3DTOP_MODULATE :  D3DTOP_DISABLE;
4341         This->StateBlock.texture_state[i][D3DTSS_COLORARG1             ] = D3DTA_TEXTURE;
4342         This->StateBlock.texture_state[i][D3DTSS_COLORARG2             ] = D3DTA_CURRENT;
4343         This->StateBlock.texture_state[i][D3DTSS_ALPHAOP               ] = (i==0)? D3DTOP_SELECTARG1 :  D3DTOP_DISABLE;
4344         This->StateBlock.texture_state[i][D3DTSS_ALPHAARG1             ] = D3DTA_TEXTURE;
4345         This->StateBlock.texture_state[i][D3DTSS_ALPHAARG2             ] = D3DTA_CURRENT;
4346         This->StateBlock.texture_state[i][D3DTSS_BUMPENVMAT00          ] = (DWORD) 0.0;
4347         This->StateBlock.texture_state[i][D3DTSS_BUMPENVMAT01          ] = (DWORD) 0.0;
4348         This->StateBlock.texture_state[i][D3DTSS_BUMPENVMAT10          ] = (DWORD) 0.0;
4349         This->StateBlock.texture_state[i][D3DTSS_BUMPENVMAT11          ] = (DWORD) 0.0;
4350         /* FIXME: This->StateBlock.texture_state[i][D3DTSS_TEXCOORDINDEX         ] = ?; */
4351         This->StateBlock.texture_state[i][D3DTSS_ADDRESSU              ] = D3DTADDRESS_WRAP;
4352         This->StateBlock.texture_state[i][D3DTSS_ADDRESSV              ] = D3DTADDRESS_WRAP;
4353         This->StateBlock.texture_state[i][D3DTSS_BORDERCOLOR           ] = 0x00;
4354         This->StateBlock.texture_state[i][D3DTSS_MAGFILTER             ] = D3DTEXF_POINT;
4355         This->StateBlock.texture_state[i][D3DTSS_MINFILTER             ] = D3DTEXF_POINT;
4356         This->StateBlock.texture_state[i][D3DTSS_MIPFILTER             ] = D3DTEXF_NONE;
4357         This->StateBlock.texture_state[i][D3DTSS_MIPMAPLODBIAS         ] = 0;
4358         This->StateBlock.texture_state[i][D3DTSS_MAXMIPLEVEL           ] = 0;
4359         This->StateBlock.texture_state[i][D3DTSS_MAXANISOTROPY         ] = 1;
4360         This->StateBlock.texture_state[i][D3DTSS_BUMPENVLSCALE         ] = (DWORD) 0.0;
4361         This->StateBlock.texture_state[i][D3DTSS_BUMPENVLOFFSET        ] = (DWORD) 0.0;
4362         This->StateBlock.texture_state[i][D3DTSS_TEXTURETRANSFORMFLAGS ] = D3DTTFF_DISABLE;
4363         This->StateBlock.texture_state[i][D3DTSS_ADDRESSW              ] = D3DTADDRESS_WRAP;
4364         This->StateBlock.texture_state[i][D3DTSS_COLORARG0             ] = D3DTA_CURRENT;
4365         This->StateBlock.texture_state[i][D3DTSS_ALPHAARG0             ] = D3DTA_CURRENT;
4366         This->StateBlock.texture_state[i][D3DTSS_RESULTARG             ] = D3DTA_CURRENT;
4367     }
4368
4369     /* Under DirectX you can have texture stage operations even if no texture is
4370        bound, whereas opengl will only do texture operations when a valid texture is
4371        bound. We emulate this by creating dummy textures and binding them to each
4372        texture stage, but disable all stages by default. Hence if a stage is enabled
4373        then the default texture will kick in until replaced by a SetTexture call     */
4374
4375     for (i=0; i<This->TextureUnits; i++) {
4376         GLubyte white = 255;
4377
4378         /* Note this avoids calling settexture, so pretend it has been called */
4379         This->StateBlock.Set.textures[i] = TRUE;
4380         This->StateBlock.Changed.textures[i] = TRUE;
4381         This->StateBlock.textures[i] = NULL;
4382
4383         /* Make appropriate texture active */
4384         if (This->isMultiTexture) {
4385             glActiveTextureARB(GL_TEXTURE0_ARB + i);
4386             checkGLcall("glActiveTextureARB");
4387         } else if (i>0) {
4388             FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
4389         }
4390
4391         /* Generate an opengl texture name */
4392         glGenTextures(1, &This->dummyTextureName[i]);
4393         checkGLcall("glGenTextures");
4394         TRACE("Dummy Texture %d given name %d\n", i, This->dummyTextureName[i]);
4395
4396         /* Generate a dummy 1d texture */
4397         This->StateBlock.textureDimensions[i] = GL_TEXTURE_1D;
4398         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
4399         checkGLcall("glBindTexture");
4400
4401         glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white); 
4402         checkGLcall("glTexImage1D");
4403
4404         /* Reapply all the texture state information to this texture */
4405         setupTextureStates(iface, i);
4406     }
4407
4408     TRACE("-----------------------> Device defaults now set up...\n");
4409
4410 }
4411
4412
4413 DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
4414     D3DRS_ALPHABLENDENABLE   ,
4415     D3DRS_ALPHAFUNC          ,
4416     D3DRS_ALPHAREF           ,
4417     D3DRS_ALPHATESTENABLE    ,
4418     D3DRS_BLENDOP            ,
4419     D3DRS_COLORWRITEENABLE   ,
4420     D3DRS_DESTBLEND          ,
4421     D3DRS_DITHERENABLE       ,
4422     D3DRS_EDGEANTIALIAS      ,
4423     D3DRS_FILLMODE           ,
4424     D3DRS_FOGDENSITY         ,
4425     D3DRS_FOGEND             ,
4426     D3DRS_FOGSTART           ,
4427     D3DRS_LASTPIXEL          ,
4428     D3DRS_LINEPATTERN        ,
4429     D3DRS_SHADEMODE          ,
4430     D3DRS_SRCBLEND           ,
4431     D3DRS_STENCILENABLE      ,
4432     D3DRS_STENCILFAIL        ,
4433     D3DRS_STENCILFUNC        ,
4434     D3DRS_STENCILMASK        ,
4435     D3DRS_STENCILPASS        ,
4436     D3DRS_STENCILREF         ,
4437     D3DRS_STENCILWRITEMASK   ,
4438     D3DRS_STENCILZFAIL       ,
4439     D3DRS_TEXTUREFACTOR      ,
4440     D3DRS_WRAP0              ,
4441     D3DRS_WRAP1              ,
4442     D3DRS_WRAP2              ,
4443     D3DRS_WRAP3              ,
4444     D3DRS_WRAP4              ,
4445     D3DRS_WRAP5              ,
4446     D3DRS_WRAP6              ,
4447     D3DRS_WRAP7              ,
4448     D3DRS_ZBIAS              ,
4449     D3DRS_ZENABLE            ,
4450     D3DRS_ZFUNC              ,
4451     D3DRS_ZWRITEENABLE
4452 };
4453
4454 DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
4455     D3DTSS_ADDRESSU              ,
4456     D3DTSS_ADDRESSV              ,
4457     D3DTSS_ADDRESSW              ,
4458     D3DTSS_ALPHAARG0             ,
4459     D3DTSS_ALPHAARG1             ,
4460     D3DTSS_ALPHAARG2             ,
4461     D3DTSS_ALPHAOP               ,
4462     D3DTSS_BORDERCOLOR           ,
4463     D3DTSS_BUMPENVLOFFSET        ,
4464     D3DTSS_BUMPENVLSCALE         ,
4465     D3DTSS_BUMPENVMAT00          ,
4466     D3DTSS_BUMPENVMAT01          ,
4467     D3DTSS_BUMPENVMAT10          ,
4468     D3DTSS_BUMPENVMAT11          ,
4469     D3DTSS_COLORARG0             ,
4470     D3DTSS_COLORARG1             ,
4471     D3DTSS_COLORARG2             ,
4472     D3DTSS_COLOROP               ,
4473     D3DTSS_MAGFILTER             ,
4474     D3DTSS_MAXANISOTROPY         ,
4475     D3DTSS_MAXMIPLEVEL           ,
4476     D3DTSS_MINFILTER             ,
4477     D3DTSS_MIPFILTER             ,
4478     D3DTSS_MIPMAPLODBIAS         ,
4479     D3DTSS_RESULTARG             ,
4480     D3DTSS_TEXCOORDINDEX         ,
4481     D3DTSS_TEXTURETRANSFORMFLAGS
4482 };
4483
4484 DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
4485     D3DRS_AMBIENT                       ,
4486     D3DRS_AMBIENTMATERIALSOURCE         ,
4487     D3DRS_CLIPPING                      ,
4488     D3DRS_CLIPPLANEENABLE               ,
4489     D3DRS_COLORVERTEX                   ,
4490     D3DRS_DIFFUSEMATERIALSOURCE         ,
4491     D3DRS_EMISSIVEMATERIALSOURCE        ,
4492     D3DRS_FOGDENSITY                    ,
4493     D3DRS_FOGEND                        ,
4494     D3DRS_FOGSTART                      ,
4495     D3DRS_FOGTABLEMODE                  ,
4496     D3DRS_FOGVERTEXMODE                 ,
4497     D3DRS_INDEXEDVERTEXBLENDENABLE      ,
4498     D3DRS_LIGHTING                      ,
4499     D3DRS_LOCALVIEWER                   ,
4500     D3DRS_MULTISAMPLEANTIALIAS          ,
4501     D3DRS_MULTISAMPLEMASK               ,
4502     D3DRS_NORMALIZENORMALS              ,
4503     D3DRS_PATCHEDGESTYLE                ,
4504     D3DRS_PATCHSEGMENTS                 ,
4505     D3DRS_POINTSCALE_A                  ,
4506     D3DRS_POINTSCALE_B                  ,
4507     D3DRS_POINTSCALE_C                  ,
4508     D3DRS_POINTSCALEENABLE              ,
4509     D3DRS_POINTSIZE                     ,
4510     D3DRS_POINTSIZE_MAX                 ,
4511     D3DRS_POINTSIZE_MIN                 ,
4512     D3DRS_POINTSPRITEENABLE             ,
4513     D3DRS_RANGEFOGENABLE                ,
4514     D3DRS_SOFTWAREVERTEXPROCESSING      ,
4515     D3DRS_SPECULARMATERIALSOURCE        ,
4516     D3DRS_TWEENFACTOR                   ,
4517     D3DRS_VERTEXBLEND
4518 };
4519
4520 DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
4521     D3DTSS_TEXCOORDINDEX         ,
4522     D3DTSS_TEXTURETRANSFORMFLAGS
4523 };