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