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