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