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