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