AddRef texture only if there is one for the requested stage.
[wine] / dlls / d3d8 / device.c
1 /*
2  * IDirect3DDevice8 implementation
3  *
4  * Copyright 2002 Jason Edmeades
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <math.h>
24 #include <stdarg.h>
25
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "wingdi.h"
32 #include "wine/debug.h"
33
34 /** define  GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
35 /*#define GL_GLEXT_PROTOTYPES*/
36 /*#undef  GLX_GLXEXT_LEGACY*/
37 #include "d3d8_private.h"
38
39 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
40 #undef GL_VERSION_1_4
41
42 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
43 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
44 WINE_DECLARE_DEBUG_CHANNEL(fps);
45
46 IDirect3DVertexShaderImpl*            VertexShaders[64];
47 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
48 IDirect3DPixelShaderImpl*             PixelShaders[64];
49
50 /* Debugging aids: */
51 #ifdef FRAME_DEBUGGING
52 BOOL isOn             = FALSE;
53 BOOL isDumpingFrames  = FALSE;
54 LONG primCounter      = 0;
55 #endif
56
57 /*
58  * Utility functions or macros
59  */
60 #define conv_mat(mat,gl_mat)                                                                \
61 do {                                                                                        \
62     TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
63     TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
64     TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
65     TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
66     memcpy(gl_mat, (mat), 16 * sizeof(float));                                              \
67 } while (0)
68
69 /* Apply the current values to the specified texture stage */
70 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
71     ICOM_THIS(IDirect3DDevice8Impl,iface);
72     int i = 0;
73     float col[4];
74     BOOL changeTexture = TRUE;
75
76     TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
77     for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
78
79         BOOL skip = FALSE;
80
81         switch (i) {
82         /* Performance: For texture states where multiples effect the outcome, only bother
83               applying the last one as it will pick up all the other values                */
84         case D3DTSS_COLORARG0:  /* Will be picked up when setting color op */
85         case D3DTSS_COLORARG1:  /* Will be picked up when setting color op */
86         case D3DTSS_COLORARG2:  /* Will be picked up when setting color op */
87         case D3DTSS_ALPHAARG0:  /* Will be picked up when setting alpha op */
88         case D3DTSS_ALPHAARG1:  /* Will be picked up when setting alpha op */
89         case D3DTSS_ALPHAARG2:  /* Will be picked up when setting alpha op */
90            skip = TRUE;
91            break;
92
93         /* Performance: If the texture states only impact settings for the texture unit 
94              (compared to the texture object) then there is no need to reapply them. The
95              only time they need applying is the first time, since we cheat and put the  
96              values into the stateblock without applying.                                
97              Per-texture unit: texture function (eg. combine), ops and args
98                                texture env color                                               
99                                texture generation settings                               
100            Note: Due to some special conditions there may be a need to do particular ones
101              of these, which is what the Flags allows                                     */
102         case D3DTSS_COLOROP:       
103         case D3DTSS_TEXCOORDINDEX:
104             if (!(Flags == REAPPLY_ALL)) skip=TRUE;
105             break;
106
107         case D3DTSS_ALPHAOP:       
108             if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
109             break;
110
111         default:
112             skip = FALSE;
113         }
114
115         if (skip == FALSE) {
116            /* Performance: Only change to this texture if we have to */
117            if (changeTexture) {
118                /* Make appropriate texture active */
119                if (GL_SUPPORT(ARB_MULTITEXTURE)) {
120 #if defined(GL_VERSION_1_3)
121                    glActiveTexture(GL_TEXTURE0 + Stage);
122 #else
123                    glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
124 #endif
125                    checkGLcall("glActiveTextureARB");
126                 } else if (Stage > 0) {
127                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
128                 }
129                 changeTexture = FALSE;
130            }
131
132            /* Now apply the change */
133            IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
134         }
135     }
136
137     /* Note the D3DRS value applies to all textures, but GL has one
138      *  per texture, so apply it now ready to be used!
139      */
140     D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
141     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
142     checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
143
144     TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
145 }
146
147 /* Convert the D3DLIGHT8 properties into equivalent gl lights */
148 void setup_light(LPDIRECT3DDEVICE8 iface, LONG Index, PLIGHTINFOEL *lightInfo) {
149
150     float quad_att;
151     float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
152     ICOM_THIS(IDirect3DDevice8Impl,iface);
153
154     /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
155     glMatrixMode(GL_MODELVIEW);
156     glPushMatrix();
157     glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
158
159     /* Diffuse: */
160     colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
161     colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
162     colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
163     colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
164     glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
165     checkGLcall("glLightfv");
166
167     /* Specular */
168     colRGBA[0] = lightInfo->OriginalParms.Specular.r;
169     colRGBA[1] = lightInfo->OriginalParms.Specular.g;
170     colRGBA[2] = lightInfo->OriginalParms.Specular.b;
171     colRGBA[3] = lightInfo->OriginalParms.Specular.a;
172     glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
173     checkGLcall("glLightfv");
174
175     /* Ambient */
176     colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
177     colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
178     colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
179     colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
180     glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
181     checkGLcall("glLightfv");
182
183     /* Attenuation - Are these right? guessing... */
184     glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
185     checkGLcall("glLightf");
186     glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
187     checkGLcall("glLightf");
188
189     quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
190     if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
191     glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
192     checkGLcall("glLightf");
193
194     switch (lightInfo->OriginalParms.Type) {
195     case D3DLIGHT_POINT:
196         /* Position */
197         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
198         checkGLcall("glLightfv");
199         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
200         checkGLcall("glLightf");
201         /* FIXME: Range */
202         break;
203
204     case D3DLIGHT_SPOT:
205         /* Position */
206         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
207         checkGLcall("glLightfv");
208         /* Direction */
209         glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
210         checkGLcall("glLightfv");
211         glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
212         checkGLcall("glLightf");
213         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
214         checkGLcall("glLightf");
215         /* FIXME: Range */
216         break;
217
218     case D3DLIGHT_DIRECTIONAL:
219         /* Direction */
220         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
221         checkGLcall("glLightfv");
222         glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
223         checkGLcall("glLightf");
224         glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
225         checkGLcall("glLightf");
226         break;
227
228     default:
229         FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
230     }
231
232     /* Restore the modelview matrix */
233     glPopMatrix();
234 }
235
236 /* Setup this textures matrix */
237 static void set_texture_matrix(float *smat, DWORD flags)
238 {
239     float mat[16];
240
241     glMatrixMode(GL_TEXTURE);
242
243     if (flags == D3DTTFF_DISABLE) {
244         glLoadIdentity();
245         checkGLcall("glLoadIdentity()");
246         return;
247     }
248
249     if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
250         ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
251         checkGLcall("glLoadIdentity()");
252         return;
253     }
254
255     memcpy(mat, smat, 16*sizeof(float));
256
257     switch (flags & ~D3DTTFF_PROJECTED) {
258     case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
259     case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
260     default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
261     }
262     
263     if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
264     case D3DTTFF_COUNT2:
265         mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
266         mat[1] = mat[5] = mat[9] = mat[13] = 0;
267         break;
268     case D3DTTFF_COUNT3:
269         mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
270         mat[2] = mat[6] = mat[10] = mat[14] = 0;
271         break;
272     }
273     glLoadMatrixf(mat);
274     checkGLcall("glLoadMatrixf(mat)");
275 }
276
277 /* IDirect3D IUnknown parts follow: */
278 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
279 {
280     ICOM_THIS(IDirect3DDevice8Impl,iface);
281
282     if (IsEqualGUID(riid, &IID_IUnknown)
283         || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
284         IDirect3DDevice8Impl_AddRef(iface);
285         *ppobj = This;
286         return D3D_OK;
287     }
288
289     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
290     return E_NOINTERFACE;
291 }
292
293 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
294     ICOM_THIS(IDirect3DDevice8Impl,iface);
295     TRACE("(%p) : AddRef from %ld\n", This, This->ref);
296     return ++(This->ref);
297 }
298
299 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
300     ICOM_THIS(IDirect3DDevice8Impl,iface);
301     ULONG ref = --This->ref;
302     TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
303     if (ref == 0) {
304       IDirect3DDevice8Impl_CleanRender(iface);
305       HeapFree(GetProcessHeap(), 0, This);
306     }
307     return ref;
308 }
309
310 /* IDirect3DDevice Interface follow: */
311 HRESULT  WINAPI  IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
312     ICOM_THIS(IDirect3DDevice8Impl,iface);
313     TRACE("(%p) : stub\n", This);    /* No way of notifying yet! */
314     return D3D_OK;
315 }
316
317 UINT     WINAPI  IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
318     ICOM_THIS(IDirect3DDevice8Impl,iface);
319     TRACE("(%p) : stub, emulating 32Mb for now\n", This);
320     /*
321      * pretend we have 32MB of any type of memory queried.
322      */
323     return (1024*1024*32);
324 }
325
326 HRESULT  WINAPI  IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
327     ICOM_THIS(IDirect3DDevice8Impl,iface);
328     FIXME("(%p) : stub\n", This);    return D3D_OK;
329 }
330 HRESULT  WINAPI  IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
331     ICOM_THIS(IDirect3DDevice8Impl,iface);
332     TRACE("(%p) : returning %p\n", This, This->direct3d8);
333
334     /* Inc ref count */
335     IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
336
337     *ppD3D8 = (IDirect3D8 *)This->direct3d8;
338     return D3D_OK;
339 }
340 HRESULT  WINAPI  IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
341     ICOM_THIS(IDirect3DDevice8Impl,iface);
342     FIXME("(%p) : stub, calling idirect3d for now\n", This);
343     IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
344     return D3D_OK;
345 }
346 HRESULT  WINAPI  IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
347
348     HDC hdc;
349     int bpp = 0;
350
351     ICOM_THIS(IDirect3DDevice8Impl,iface);
352     pMode->Width        = GetSystemMetrics(SM_CXSCREEN);
353     pMode->Height       = GetSystemMetrics(SM_CYSCREEN);
354     pMode->RefreshRate  = 85; /*FIXME: How to identify? */
355
356     hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
357     bpp = GetDeviceCaps(hdc, BITSPIXEL);
358     DeleteDC(hdc);
359
360     switch (bpp) {
361     case  8: pMode->Format       = D3DFMT_R8G8B8; break;
362     case 16: pMode->Format       = D3DFMT_R5G6B5; break;
363     case 24: /*pMode->Format       = D3DFMT_R8G8B8; break; */
364     case 32: pMode->Format       = D3DFMT_A8R8G8B8; break;
365     default: 
366        FIXME("Unrecognized display mode format\n");
367        pMode->Format       = D3DFMT_UNKNOWN;
368     }
369
370     FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, 
371           pMode->Format, debug_d3dformat(pMode->Format));
372     return D3D_OK;
373 }
374 HRESULT  WINAPI  IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
375     ICOM_THIS(IDirect3DDevice8Impl,iface);
376     TRACE("(%p) copying to %p\n", This, pParameters);    
377     memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
378     return D3D_OK;
379 }
380 HRESULT  WINAPI  IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
381     IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
382     ICOM_THIS(IDirect3DDevice8Impl,iface);
383     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
384
385     if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
386       ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
387       return D3DERR_INVALIDCALL;
388     }
389     if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
390       ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
391       return D3DERR_INVALIDCALL;
392     }
393
394     This->xHotSpot = XHotSpot;
395     This->yHotSpot = YHotSpot;
396     return D3D_OK;
397 }
398 void     WINAPI  IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
399     ICOM_THIS(IDirect3DDevice8Impl,iface);
400     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
401     This->xScreenSpace = XScreenSpace;
402     This->yScreenSpace = YScreenSpace;
403     return;
404 }
405 BOOL     WINAPI  IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
406     ICOM_THIS(IDirect3DDevice8Impl,iface);
407     TRACE("(%p) : visible(%d)\n", This, bShow); 
408     This->bCursorVisible = bShow;
409     return D3D_OK;
410 }
411 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
412     IDirect3DSwapChain8Impl* object;
413     ICOM_THIS(IDirect3DDevice8Impl,iface);
414     FIXME("(%p) : stub\n", This);
415
416     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
417     if (NULL == object) {
418       return D3DERR_OUTOFVIDEOMEMORY;
419     }
420     object->lpVtbl = &Direct3DSwapChain8_Vtbl;
421     object->ref = 1;
422
423     TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This, 
424           pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
425           pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
426
427     if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth  == 0) ||
428                                               (pPresentationParameters->BackBufferHeight == 0))) {
429       RECT Rect;
430       
431       GetClientRect(This->win_handle, &Rect);
432       
433       if (pPresentationParameters->BackBufferWidth == 0) {
434         pPresentationParameters->BackBufferWidth = Rect.right;
435         TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
436       }
437       if (pPresentationParameters->BackBufferHeight == 0) {
438         pPresentationParameters->BackBufferHeight = Rect.bottom;
439         TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
440       }
441     }
442     
443     /* Save the presentation parms now filled in correctly */
444     memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
445
446     IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
447                                             pPresentationParameters->BackBufferWidth,
448                                             pPresentationParameters->BackBufferHeight,
449                                             pPresentationParameters->BackBufferFormat,
450                                             pPresentationParameters->MultiSampleType,
451                                             TRUE,
452                                             (LPDIRECT3DSURFACE8*) &object->frontBuffer);
453     
454     IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
455                                             pPresentationParameters->BackBufferWidth,
456                                             pPresentationParameters->BackBufferHeight,
457                                             pPresentationParameters->BackBufferFormat,
458                                             pPresentationParameters->MultiSampleType,
459                                             TRUE,
460                                             (LPDIRECT3DSURFACE8*) &object->backBuffer);
461
462     if (pPresentationParameters->EnableAutoDepthStencil) {
463        IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
464                                                       pPresentationParameters->BackBufferWidth,
465                                                       pPresentationParameters->BackBufferHeight,
466                                                       pPresentationParameters->AutoDepthStencilFormat,
467                                                       D3DMULTISAMPLE_NONE,
468                                                       (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
469     } else {
470       object->depthStencilBuffer = NULL;
471     }
472
473     *pSwapChain = (IDirect3DSwapChain8*) object;
474     return D3D_OK;
475 }
476 HRESULT  WINAPI  IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
477     ICOM_THIS(IDirect3DDevice8Impl,iface);
478     FIXME("(%p) : stub\n", This);    return D3D_OK;
479 }
480 HRESULT  WINAPI  IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
481     ICOM_THIS(IDirect3DDevice8Impl,iface);
482     TRACE("(%p) : complete stub!\n", This);
483
484     ENTER_GL();
485
486     if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
487
488
489     glXSwapBuffers(This->display, This->drawable);
490     /* Don't call checkGLcall, as glGetError is not applicable here */
491     TRACE("glXSwapBuffers called, Starting new frame\n");
492
493     /* FPS support */
494     if (TRACE_ON(fps))
495     {
496         static long prev_time, frames;
497
498         DWORD time = GetTickCount();
499         frames++;
500         /* every 1.5 seconds */
501         if (time - prev_time > 1500) {
502             TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
503             prev_time = time;
504             frames = 0;
505         }
506     }
507
508 #if defined(FRAME_DEBUGGING)
509 {
510     if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
511         if (!isOn) {
512             isOn = TRUE;
513             FIXME("Enabling D3D Trace\n");
514             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
515 #if defined(SHOW_FRAME_MAKEUP)
516             FIXME("Singe Frame snapshots Starting\n");
517             isDumpingFrames = TRUE;
518             glClear(GL_COLOR_BUFFER_BIT);
519 #endif
520
521 #if defined(SINGLE_FRAME_DEBUGGING)
522         } else {
523 #if defined(SHOW_FRAME_MAKEUP)
524             FIXME("Singe Frame snapshots Finishing\n");
525             isDumpingFrames = FALSE;
526 #endif
527             FIXME("Singe Frame trace complete\n");
528             DeleteFileA("C:\\D3DTRACE");
529             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
530 #endif
531         }
532     } else {
533         if (isOn) {
534             isOn = FALSE;
535 #if defined(SHOW_FRAME_MAKEUP)
536             FIXME("Singe Frame snapshots Finishing\n");
537             isDumpingFrames = FALSE;
538 #endif
539             FIXME("Disabling D3D Trace\n");
540             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
541         }
542     }
543 }
544 #endif
545
546     LEAVE_GL();
547     /* Although this is not strictly required, a simple demo showed this does occur
548        on (at least non-debug) d3d                                                  */
549     if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
550        IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
551     }
552
553     return D3D_OK;
554 }
555 HRESULT  WINAPI  IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
556     ICOM_THIS(IDirect3DDevice8Impl,iface);
557     *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
558     TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
559
560     if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
561         FIXME("Only one backBuffer currently supported\n");
562         return D3DERR_INVALIDCALL;
563     }
564
565     /* Note inc ref on returned surface */
566     IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
567
568     return D3D_OK;
569 }
570 HRESULT  WINAPI  IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
571     ICOM_THIS(IDirect3DDevice8Impl,iface);
572     FIXME("(%p) : stub\n", This);    
573     return D3D_OK;
574 }
575 void     WINAPI  IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
576     HDC hDC;
577     ICOM_THIS(IDirect3DDevice8Impl,iface);
578
579     FIXME("(%p) : pRamp@%p\n", This, pRamp);
580     hDC = GetDC(This->win_handle);
581     SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
582     ReleaseDC(This->win_handle, hDC);
583     return;
584 }
585 void     WINAPI  IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
586     HDC hDC;
587     ICOM_THIS(IDirect3DDevice8Impl,iface);
588
589     FIXME("(%p) : pRamp@%p\n", This, pRamp);
590     hDC = GetDC(This->win_handle);
591     GetDeviceGammaRamp(hDC, pRamp);
592     ReleaseDC(This->win_handle, hDC);
593     return;
594 }
595 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
596                                                     D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
597     IDirect3DTexture8Impl *object;
598     int i;
599     UINT tmpW;
600     UINT tmpH;
601
602     ICOM_THIS(IDirect3DDevice8Impl,iface);
603
604     /* Allocate the storage for the device */
605     TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, debug_d3dformat(Format), Pool);
606     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
607     object->lpVtbl = &Direct3DTexture8_Vtbl;
608     object->Device = This;
609     object->ResourceType = D3DRTYPE_TEXTURE;
610     object->ref = 1;
611     object->width = Width;
612     object->height = Height;
613     object->levels = Levels;
614     object->usage = Usage;
615     object->format = Format;
616
617     /* Calculate levels for mip mapping */
618     if (Levels == 0) {
619         object->levels++;
620         tmpW = Width;
621         tmpH = Height;
622         while (tmpW > 1 && tmpH > 1) {
623             tmpW = max(1, tmpW / 2);
624             tmpH = max(1, tmpH / 2);
625             object->levels++;
626         }
627         TRACE("Calculated levels = %d\n", object->levels);
628     }
629
630     /* Generate all the surfaces */
631     tmpW = Width;
632     tmpH = Height;
633     for (i = 0; i < object->levels; i++) 
634     {
635         IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
636         object->surfaces[i]->Container = (IUnknown*) object;
637         object->surfaces[i]->myDesc.Usage = Usage;
638         object->surfaces[i]->myDesc.Pool = Pool;
639         /** 
640          * As written in msdn in IDirect3DTexture8::LockRect
641          *  Textures created in D3DPOOL_DEFAULT are not lockable.
642          */
643         if (D3DPOOL_DEFAULT == Pool) {
644           object->surfaces[i]->lockable = FALSE;
645         }
646
647         TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
648         tmpW = max(1, tmpW / 2);
649         tmpH = max(1, tmpH / 2);
650     }
651
652     *ppTexture = (LPDIRECT3DTEXTURE8) object;
653     TRACE("(%p) : Created texture %p\n", This, object);
654     return D3D_OK;
655 }
656 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface, 
657                                                           UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, 
658                                                           D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
659
660     IDirect3DVolumeTexture8Impl *object;
661     int i;
662     UINT tmpW;
663     UINT tmpH;
664     UINT tmpD;
665
666     ICOM_THIS(IDirect3DDevice8Impl,iface);
667
668     /* Allocate the storage for it */
669     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
670     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
671     object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
672     object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
673     object->Device = This;
674     object->ref = 1;
675
676     object->width = Width;
677     object->height = Height;
678     object->depth = Depth;
679     object->levels = Levels;
680     object->usage = Usage;
681     object->format = Format;
682
683     /* Calculate levels for mip mapping */
684     if (Levels == 0) {
685         object->levels++;
686         tmpW = Width;
687         tmpH = Height;
688         tmpD = Depth;
689         while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
690             tmpW = max(1, tmpW / 2);
691             tmpH = max(1, tmpH / 2);
692             tmpD = max(1, tmpD / 2);
693             object->levels++;
694         }
695         TRACE("Calculated levels = %d\n", object->levels);
696     }
697
698     /* Generate all the surfaces */
699     tmpW = Width;
700     tmpH = Height;
701     tmpD = Depth;
702
703     for (i = 0; i < object->levels; i++) 
704     {
705         IDirect3DVolume8Impl* volume;
706
707         /* Create the volume - No entry point for this seperately?? */
708         volume  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
709         object->volumes[i] = (IDirect3DVolume8Impl *) volume;
710
711         volume->lpVtbl = &Direct3DVolume8_Vtbl;
712         volume->Device = This;
713         volume->ResourceType = D3DRTYPE_VOLUME;
714         volume->Container = (IUnknown*) object;
715         volume->ref = 1;
716
717         volume->myDesc.Width  = Width;
718         volume->myDesc.Height = Height;
719         volume->myDesc.Depth  = Depth;
720         volume->myDesc.Format = Format;
721         volume->myDesc.Type   = D3DRTYPE_VOLUME;
722         volume->myDesc.Pool   = Pool;
723         volume->myDesc.Usage  = Usage;
724         volume->bytesPerPixel   = D3DFmtGetBpp(This, Format);
725         /* Note: Volume textures cannot be dxtn, hence no need to check here */
726         volume->myDesc.Size     = (Width * volume->bytesPerPixel) * Height * Depth; 
727         volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
728
729         volume->lockable = TRUE;
730         volume->locked = FALSE;
731         memset(&volume->lockedBox, 0, sizeof(D3DBOX));
732         volume->Dirty = FALSE;
733         IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
734
735         TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n", 
736               This, Width, Height, Depth, Format, debug_d3dformat(Format),
737               volume, volume->allocatedMemory, volume->myDesc.Size);
738
739         tmpW = max(1, tmpW / 2);
740         tmpH = max(1, tmpH / 2);
741         tmpD = max(1, tmpD / 2);
742     }
743
744     *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
745     TRACE("(%p) : Created volume texture %p\n", This, object);
746     return D3D_OK;
747 }
748 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage, 
749                                                         D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
750
751     IDirect3DCubeTexture8Impl *object;
752     ICOM_THIS(IDirect3DDevice8Impl,iface);
753     int i,j;
754     UINT tmpW;
755
756     /* Allocate the storage for it */
757     TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, EdgeLength, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
758     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
759     object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
760     object->ref = 1;
761     object->Device = This;
762     object->ResourceType = D3DRTYPE_CUBETEXTURE;
763
764     object->edgeLength = EdgeLength;
765     object->levels = Levels;
766     object->usage = Usage;
767     object->format = Format;
768
769     /* Calculate levels for mip mapping */
770     if (Levels == 0) {
771         object->levels++;
772         tmpW = EdgeLength;
773         while (tmpW > 1) {
774             tmpW = max(1, tmpW / 2);
775             object->levels++;
776         }
777         TRACE("Calculated levels = %d\n", object->levels);
778     }
779
780     /* Generate all the surfaces */
781     tmpW = EdgeLength;
782     for (i = 0; i < object->levels; i++) {
783         /* Create the 6 faces */
784         for (j = 0; j < 6; j++) {
785            IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
786            object->surfaces[j][i]->Container = (IUnknown*) object;
787            object->surfaces[j][i]->myDesc.Usage = Usage;
788            object->surfaces[j][i]->myDesc.Pool = Pool;
789            /** 
790             * As written in msdn in IDirect3DCubeTexture8::LockRect
791             *  Textures created in D3DPOOL_DEFAULT are not lockable.
792             */
793            if (D3DPOOL_DEFAULT == Pool) {
794              object->surfaces[j][i]->lockable = FALSE;
795            }
796
797            TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
798         }
799         tmpW = max(1, tmpW / 2);
800     }
801
802     TRACE("(%p) : Iface@%p\n", This, object);
803     *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
804     return D3D_OK;
805 }
806 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
807     IDirect3DVertexBuffer8Impl *object;
808
809     ICOM_THIS(IDirect3DDevice8Impl,iface);
810
811     /* Allocate the storage for the device */
812     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
813     object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
814     object->Device = This;
815     object->ResourceType = D3DRTYPE_VERTEXBUFFER;
816     object->ref = 1;
817     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
818     object->currentDesc.Usage = Usage;
819     object->currentDesc.Pool  = Pool;
820     object->currentDesc.FVF   = FVF;
821     object->currentDesc.Size  = Size;
822
823     TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
824
825     *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
826
827     return D3D_OK;
828 }
829 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
830     IDirect3DIndexBuffer8Impl *object;
831
832     ICOM_THIS(IDirect3DDevice8Impl,iface);
833     TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
834
835     /* Allocate the storage for the device */
836     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
837     object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
838     object->Device = This;
839     object->ref = 1;
840     object->ResourceType = D3DRTYPE_INDEXBUFFER;
841
842     object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
843     object->currentDesc.Usage = Usage;
844     object->currentDesc.Pool  = Pool;
845     object->currentDesc.Format  = Format;
846     object->currentDesc.Size  = Length;
847
848     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
849
850     TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
851
852     *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
853
854     return D3D_OK;
855 }
856 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
857     IDirect3DSurface8Impl *object;
858     ICOM_THIS(IDirect3DDevice8Impl,iface);
859     
860     object  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
861     if (NULL == object) {
862       *ppSurface = NULL;
863       return D3DERR_OUTOFVIDEOMEMORY;
864     }
865     *ppSurface = (LPDIRECT3DSURFACE8) object;
866     object->lpVtbl = &Direct3DSurface8_Vtbl;
867     object->Device = This;
868     object->ResourceType = D3DRTYPE_SURFACE;
869     object->Container = (IUnknown*) This;
870
871     object->ref = 1;
872     object->myDesc.Width  = Width;
873     object->myDesc.Height = Height;
874     object->myDesc.Format = Format;
875     object->myDesc.Type = D3DRTYPE_SURFACE;
876     object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
877     object->myDesc.Pool = D3DPOOL_DEFAULT;
878     object->myDesc.MultiSampleType = MultiSample;
879     object->bytesPerPixel = D3DFmtGetBpp(This, Format);
880     if (Format == D3DFMT_DXT1) { 
881         object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height;  /* DXT1 is half byte per pixel */
882     } else {
883         object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
884     }
885     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
886     object->lockable = Lockable;
887     object->locked = FALSE;
888     memset(&object->lockedRect, 0, sizeof(RECT));
889     IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
890
891     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), Lockable, *ppSurface, object->allocatedMemory, object->myDesc.Size);
892     return D3D_OK;
893 }
894 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
895     IDirect3DSurface8Impl *object;
896
897     ICOM_THIS(IDirect3DDevice8Impl,iface);
898
899     object  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
900     if (NULL == object) {
901       *ppSurface = NULL;
902       return D3DERR_OUTOFVIDEOMEMORY;
903     }
904     *ppSurface = (LPDIRECT3DSURFACE8) object;
905     object->lpVtbl = &Direct3DSurface8_Vtbl;
906     object->Device = This;
907     object->ResourceType = D3DRTYPE_SURFACE;
908     object->Container = (IUnknown*) This;
909
910     object->ref = 1;
911     object->myDesc.Width  = Width;
912     object->myDesc.Height = Height;
913     object->myDesc.Format = Format;
914     object->myDesc.Type = D3DRTYPE_SURFACE;
915     object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
916     object->myDesc.Pool = D3DPOOL_DEFAULT;
917     object->myDesc.MultiSampleType = MultiSample;
918     object->bytesPerPixel = D3DFmtGetBpp(This, Format);
919     if (Format == D3DFMT_DXT1) { 
920         object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
921     } else {
922         object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
923     }
924     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
925     object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
926     object->locked = FALSE;
927     memset(&object->lockedRect, 0, sizeof(RECT));
928     IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
929
930     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), *ppSurface, object->allocatedMemory, object->myDesc.Size);
931     return D3D_OK;
932 }
933 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
934     IDirect3DSurface8Impl *object;
935
936     ICOM_THIS(IDirect3DDevice8Impl,iface);
937
938     object  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
939     *ppSurface = (LPDIRECT3DSURFACE8) object;
940     object->lpVtbl = &Direct3DSurface8_Vtbl;
941     object->Device = This;
942     object->ResourceType = D3DRTYPE_SURFACE;
943     object->Container = (IUnknown*) This;
944
945     object->ref = 1;
946     object->myDesc.Width  = Width;
947     object->myDesc.Height = Height;
948     object->myDesc.Format = Format;
949     object->myDesc.Type = D3DRTYPE_SURFACE;
950     object->myDesc.Usage = 0;
951     object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
952     object->bytesPerPixel = D3DFmtGetBpp(This, Format);
953     /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
954        it is based around 4x4 pixel blocks it requires padding, so allocate enough
955        space!                                                                      */
956     if (Format == D3DFMT_DXT1) { 
957         object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
958     } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 || 
959                Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) { 
960         object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
961     } else {
962         object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
963     }
964     object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
965     object->lockable = TRUE;
966     object->locked = FALSE;
967     memset(&object->lockedRect, 0, sizeof(RECT));
968     IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
969
970     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), *ppSurface, object->allocatedMemory, object->myDesc.Size);
971     return D3D_OK;
972 }
973 HRESULT  WINAPI  IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, 
974                                                 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
975                                                 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
976
977     HRESULT rc = D3D_OK;
978     IDirect3DBaseTexture8* texture = NULL;
979
980
981     IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
982     IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
983
984     ICOM_THIS(IDirect3DDevice8Impl,iface);
985     TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
986           pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
987
988     /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
989          a sample and doesn't seem to break anything as far as I can tell               */
990     if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
991         TRACE("Formats do not match (%x,%s) / (%x,%s)\n", 
992                src->myDesc.Format, debug_d3dformat(src->myDesc.Format), 
993                dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
994         rc = D3DERR_INVALIDCALL;
995
996     } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
997         TRACE("Converting dest to same format as source, since dest was unknown\n");
998         dst->myDesc.Format = src->myDesc.Format;
999
1000         /* Convert container as well */
1001         rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1002         if (SUCCEEDED(rc) && NULL != texture) {
1003             ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1004             /** Releasing texture after GetContainer */
1005             IDirect3DBaseTexture8_Release(texture);
1006             texture = NULL;
1007         }
1008     }
1009
1010     /* Quick if complete copy ... */
1011     if (SUCCEEDED(rc)) {
1012       if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1013
1014         if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1015           
1016           D3DLOCKED_RECT lrSrc;
1017           D3DLOCKED_RECT lrDst;
1018           IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1019           IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1020           TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1021           
1022           memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1023           
1024           IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1025           rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1026           TRACE("Unlocked src and dst\n");
1027           
1028         } else {
1029           
1030           FIXME("Wanted to copy all surfaces but size not compatible\n");
1031           rc = D3DERR_INVALIDCALL;
1032           
1033         }
1034
1035       } else {
1036         
1037         if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1038
1039           int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1040           int i;
1041
1042           /* Copy rect by rect */
1043           for (i = 0; i < cRects; i++) {
1044             CONST RECT*  r = &pSourceRectsArray[i];
1045             CONST POINT* p = &pDestPointsArray[i];
1046             int copyperline;
1047             int j;
1048             D3DLOCKED_RECT lrSrc;
1049             D3DLOCKED_RECT lrDst;
1050             RECT dest_rect;
1051  
1052             TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1053             if (src->myDesc.Format == D3DFMT_DXT1) { 
1054               copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1055             } else {
1056                 copyperline = ((r->right - r->left) * bytesPerPixel);
1057             }
1058             IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1059             dest_rect.left  = p->x;
1060             dest_rect.top   = p->y;
1061             dest_rect.right = p->x + (r->right - r->left);
1062             dest_rect.bottom= p->y + (r->bottom - r->top);
1063             IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1064             TRACE("Locked src and dst\n");
1065
1066             /* Find where to start */
1067             for (j = 0; j < (r->bottom - r->top - 1); j++) {
1068               memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1069             }
1070             IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1071             rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1072             TRACE("Unlocked src and dst\n");
1073           }
1074         } else {
1075           FIXME("Wanted to copy partial surfaces not implemented\n");
1076           rc = D3DERR_INVALIDCALL;                
1077         }
1078       }
1079     }
1080
1081     return rc;
1082 }
1083 HRESULT  WINAPI  IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1084     IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1085     IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1086     D3DRESOURCETYPE srcType;
1087     D3DRESOURCETYPE dstType;
1088
1089     ICOM_THIS(IDirect3DDevice8Impl,iface);
1090     TRACE("(%p) : first try\n", This);
1091
1092     srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1093     dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1094
1095     if (srcType != dstType) {
1096       return D3DERR_INVALIDCALL;
1097     }
1098     if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1099       return D3DERR_INVALIDCALL;
1100     }
1101     if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1102       return D3DERR_INVALIDCALL;
1103     }
1104     if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1105       /** Only copy Dirty textures */
1106       DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1107       DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1108       DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1109       UINT i, j;
1110
1111       for (i = skipLevels; i < srcLevelCnt; ++i) {
1112         HRESULT hr;
1113
1114         switch (srcType) { 
1115         case D3DRTYPE_TEXTURE:
1116           {
1117             IDirect3DSurface8* srcSur = NULL;
1118             IDirect3DSurface8* dstSur = NULL;
1119             hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1120             hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1121
1122             /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1123                         about dst with less levels than the source?)                               */
1124             IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1125
1126             IDirect3DSurface8Impl_Release(srcSur);
1127             IDirect3DSurface8Impl_Release(dstSur);
1128           }
1129           break;
1130         case D3DRTYPE_VOLUMETEXTURE:
1131           {
1132             FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1133           }
1134           break;
1135         case D3DRTYPE_CUBETEXTURE:
1136           {
1137             IDirect3DSurface8* srcSur = NULL;
1138             IDirect3DSurface8* dstSur = NULL;
1139             for (j = 0; j < 5; ++j) {
1140               hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1141               hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1142               FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1143               IDirect3DSurface8Impl_Release(srcSur);
1144               IDirect3DSurface8Impl_Release(dstSur);
1145             }
1146           }
1147           break;
1148         default:
1149           break;
1150         }
1151       }
1152       IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1153     }
1154     
1155     return D3D_OK;
1156 }
1157 HRESULT  WINAPI  IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1158     HRESULT hr;
1159     D3DLOCKED_RECT lockedRect;
1160     RECT wantedRect;
1161     GLint  prev_store;
1162     GLenum prev_read;
1163
1164     ICOM_THIS(IDirect3DDevice8Impl,iface);
1165
1166     FIXME("(%p) : see if behavior correct\n", This);
1167
1168     if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1169       ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1170       return D3DERR_INVALIDCALL;
1171     }
1172     
1173     wantedRect.left = 0;
1174     wantedRect.top = 0;
1175     wantedRect.right = This->PresentParms.BackBufferWidth;
1176     wantedRect.bottom = This->PresentParms.BackBufferHeight;
1177     
1178     hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1179     if (FAILED(hr)) {
1180       ERR("(%p) : cannot lock surface\n", This);
1181       return D3DERR_INVALIDCALL;
1182     }
1183
1184     ENTER_GL();
1185
1186     glFlush();
1187     vcheckGLcall("glFlush");
1188     glGetIntegerv(GL_READ_BUFFER, &prev_read);
1189     vcheckGLcall("glIntegerv");
1190     glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1191     vcheckGLcall("glIntegerv");
1192  
1193     glReadBuffer(GL_FRONT);
1194     vcheckGLcall("glReadBuffer");
1195     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1196     vcheckGLcall("glPixelStorei");
1197     /* stupid copy */
1198     {
1199       long j;
1200       for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1201         /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
1202         glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1203                      GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1204         vcheckGLcall("glReadPixels");
1205       }
1206     }
1207     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1208     vcheckGLcall("glPixelStorei");
1209     glReadBuffer(prev_read);
1210     vcheckGLcall("glReadBuffer");
1211
1212     LEAVE_GL();
1213
1214     hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1215     return hr;
1216 }
1217 HRESULT  WINAPI  IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1218     HRESULT hr;
1219
1220     ICOM_THIS(IDirect3DDevice8Impl,iface);
1221
1222     if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1223       TRACE("Trying to do a NOP SetRenderTarget operation\n");
1224       return D3D_OK;
1225     }
1226
1227     IDirect3DDevice8Impl_CleanRender(iface);
1228
1229     if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1230       IDirect3DSurface8Impl* tmp;
1231
1232       TRACE("retoring SetRenderTarget defaults\n");
1233
1234       tmp = This->renderTarget;
1235       This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
1236       IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
1237       IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1238       
1239       tmp = This->stencilBufferTarget;
1240       This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
1241       if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
1242       if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1243
1244       return D3D_OK;
1245     }
1246
1247     TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1248
1249     hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1250     
1251     return hr;
1252 }
1253
1254 HRESULT  WINAPI  IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1255     ICOM_THIS(IDirect3DDevice8Impl,iface);
1256
1257     TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1258     
1259     *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1260     IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1261     
1262     return D3D_OK;
1263 }
1264
1265 HRESULT  WINAPI  IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1266     ICOM_THIS(IDirect3DDevice8Impl,iface);
1267
1268     TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1269     
1270     /* Note inc ref on returned surface */
1271     *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1272     if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1273
1274     return D3D_OK;
1275 }
1276
1277 HRESULT  WINAPI  IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1278     ICOM_THIS(IDirect3DDevice8Impl,iface);
1279     TRACE("(%p) : stub\n", This);
1280     return D3D_OK;
1281 }
1282 HRESULT  WINAPI  IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1283     IDirect3DBaseTexture8* cont = NULL;
1284     HRESULT hr;
1285     ICOM_THIS(IDirect3DDevice8Impl,iface);
1286     TRACE("(%p)\n", This);
1287
1288     ENTER_GL();
1289
1290     glFlush();
1291     checkGLcall("glFlush");
1292
1293     /* Useful for debugging sometimes!
1294     printf("Hit Enter ...\n");
1295     getchar(); */
1296
1297     if (This->frontBuffer != This->renderTarget) {
1298       {
1299         GLenum prev_read;
1300         glGetIntegerv(GL_READ_BUFFER, &prev_read);
1301         vcheckGLcall("glIntegerv");
1302         glReadBuffer(GL_BACK);
1303         vcheckGLcall("glReadBuffer");
1304         {
1305           long j;
1306           long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1307
1308           if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1309               pitch = pitch / 2;
1310
1311           for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1312             glReadPixels(0, 
1313                          This->renderTarget->myDesc.Height - j - 1, 
1314                          This->renderTarget->myDesc.Width, 
1315                          1,
1316                          D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format), 
1317                          D3DFmt2GLType(This, This->renderTarget->myDesc.Format), 
1318                          This->renderTarget->allocatedMemory + j * pitch);
1319             vcheckGLcall("glReadPixels");
1320           }
1321         }      
1322         glReadBuffer(prev_read);
1323         vcheckGLcall("glReadBuffer");
1324       }
1325
1326       hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1327       if (SUCCEEDED(hr) && NULL != cont) {
1328         /** always dirtify for now. we must find a better way to see that surface have been modified */
1329         IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1330         IDirect3DBaseTexture8_PreLoad(cont);
1331         IDirect3DBaseTexture8Impl_Release(cont);
1332         cont = NULL;
1333       }
1334     }
1335
1336     LEAVE_GL();
1337     return D3D_OK;
1338 }
1339 HRESULT  WINAPI  IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1340     ICOM_THIS(IDirect3DDevice8Impl,iface);
1341
1342     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1343       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1344       when the depth-buffer format does not contain stencil buffer information, this method fails. */
1345     GLbitfield glMask = 0;
1346     GLboolean old_ztest;
1347     GLfloat old_z_clear_value;
1348     GLint   old_stencil_clear_value;
1349     GLfloat old_color_clear_value[4];
1350     int i;
1351     CONST D3DRECT* curRect;
1352
1353     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1354           Count, pRects, Flags, Z, Stencil);
1355
1356     ENTER_GL();
1357     glEnable(GL_SCISSOR_TEST);
1358     checkGLcall("glEnable GL_SCISSOR_TEST");
1359     if (Count > 0 && pRects) {
1360         curRect = pRects;
1361     } else {
1362         curRect = NULL;
1363     }
1364
1365     /* Only set the values up once, as they are not changing */
1366     if (Flags & D3DCLEAR_STENCIL) {     
1367         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1368         glClearStencil(Stencil);
1369         checkGLcall("glClearStencil");
1370         glMask = glMask | GL_STENCIL_BUFFER_BIT;
1371         glStencilMask(0xFFFFFFFF);
1372     }
1373
1374     if (Flags & D3DCLEAR_ZBUFFER) {
1375         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1376         glDepthMask(GL_TRUE); 
1377         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1378         glClearDepth(Z);
1379         checkGLcall("glClearDepth");
1380         glMask = glMask | GL_DEPTH_BUFFER_BIT;
1381     }
1382
1383     if (Flags & D3DCLEAR_TARGET) {
1384         TRACE("Clearing screen with glClear to color %lx\n", Color);
1385         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1386         glClearColor(((Color >> 16) & 0xFF) / 255.0f, 
1387                      ((Color >>  8) & 0xFF) / 255.0f,
1388                      ((Color >>  0) & 0xFF) / 255.0f, 
1389                      ((Color >> 24) & 0xFF) / 255.0f);
1390         checkGLcall("glClearColor");
1391
1392         /* Clear ALL colors! */
1393         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1394         glMask = glMask | GL_COLOR_BUFFER_BIT;
1395     }
1396
1397     /* Now process each rect in turn */
1398     for (i = 0; i < Count || i == 0; i++) {
1399
1400         if (curRect) {
1401             /* Note gl uses lower left, width/height */
1402             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1403                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1404                   curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2), 
1405                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1406             glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2), 
1407                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1408             checkGLcall("glScissor");
1409         } else {
1410             glScissor(This->StateBlock->viewport.X, 
1411                       (This->PresentParms.BackBufferHeight - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)), 
1412                       This->StateBlock->viewport.Width, 
1413                       This->StateBlock->viewport.Height);
1414             checkGLcall("glScissor");
1415         }
1416
1417         /* Clear the selected rectangle (or full screen) */
1418         glClear(glMask);
1419         checkGLcall("glClear");
1420
1421         /* Step to the next rectangle */
1422         if (curRect) curRect = curRect + sizeof(D3DRECT);
1423     }
1424
1425     /* Restore the old values (why..?) */
1426     if (Flags & D3DCLEAR_STENCIL) {
1427         glClearStencil(old_stencil_clear_value);
1428         glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1429     }    
1430     if (Flags & D3DCLEAR_ZBUFFER) {
1431         glDepthMask(old_ztest);
1432         glClearDepth(old_z_clear_value);
1433     }
1434     if (Flags & D3DCLEAR_TARGET) {
1435         glClearColor(old_color_clear_value[0], 
1436                      old_color_clear_value[1],
1437                      old_color_clear_value[2], 
1438                      old_color_clear_value[3]);
1439         glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE, 
1440                     This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1441                     This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE, 
1442                     This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1443     }
1444
1445     glDisable(GL_SCISSOR_TEST);
1446     checkGLcall("glDisable");
1447     LEAVE_GL();
1448
1449     return D3D_OK;
1450 }
1451 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1452     ICOM_THIS(IDirect3DDevice8Impl,iface);
1453     int k;
1454
1455     /* Most of this routine, comments included copied from ddraw tree initially: */
1456     TRACE("(%p) : State=%d\n", This, d3dts);
1457
1458     /* Handle recording of state blocks */
1459     if (This->isRecordingState) {
1460         TRACE("Recording... not performing anything\n");
1461         This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1462         This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1463         memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1464         return D3D_OK;
1465     }
1466
1467     /*
1468      * if the new matrix is the same as the current one,
1469      * we cut off any further processing. this seems to be a reasonable
1470      * optimization because as was noticed, some apps (warcraft3 for example)
1471      * tend towards setting the same matrix repeatedly for some dumb reason.
1472      *
1473      * From here on we assume that the new matrix is different, wherever it matters
1474      * but note
1475      */
1476     if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1477         TRACE("The app is setting the same matrix over again\n");
1478         return D3D_OK;
1479     } else {
1480         conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1481     }
1482
1483     /*
1484        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1485        where ViewMat = Camera space, WorldMat = world space.
1486
1487        In OpenGL, camera and world space is combined into GL_MODELVIEW
1488        matrix.  The Projection matrix stay projection matrix. 
1489      */
1490
1491     /* Capture the times we can just ignore the change */
1492     if (d3dts == D3DTS_WORLDMATRIX(0)) {
1493         This->modelview_valid = FALSE;
1494         return D3D_OK;
1495
1496     } else if (d3dts == D3DTS_PROJECTION) {
1497         This->proj_valid = FALSE;
1498         return D3D_OK;
1499
1500     } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511  */
1501         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1502         FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1503         return D3D_OK;
1504     } 
1505     
1506     /* Chances are we really are going to have to change a matrix */
1507     ENTER_GL();
1508
1509     if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1510         if (d3dts < GL_LIMITS(textures)) {
1511             int tex = d3dts - D3DTS_TEXTURE0;
1512 #if defined(GL_VERSION_1_3)
1513             glActiveTexture(GL_TEXTURE0 + tex);
1514 #else 
1515             glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1516 #endif
1517             set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1518         }
1519
1520     } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1521
1522         PLIGHTINFOEL *lightChain = NULL;
1523         float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1524         This->modelview_valid = FALSE;
1525         This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1526         glMatrixMode(GL_MODELVIEW);
1527         checkGLcall("glMatrixMode(GL_MODELVIEW)");
1528         glPushMatrix();
1529         glLoadMatrixf((float *)lpmatrix);
1530         checkGLcall("glLoadMatrixf(...)");
1531
1532         /* If we are changing the View matrix, reset the light and clipping planes to the new view   
1533          * NOTE: We have to reset the positions even if the light/plane is not currently
1534          *       enabled, since the call to enable it will not reset the position.                 
1535          * NOTE2: Apparently texture transforms do NOT need reapplying
1536          */
1537
1538         /* Reset lights */
1539         lightChain = This->StateBlock->lights;
1540         while (lightChain && lightChain->glIndex != -1) {
1541             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1542             checkGLcall("glLightfv posn");
1543             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1544             checkGLcall("glLightfv dirn");
1545             lightChain = lightChain->next;
1546         }
1547         /* Reset Clipping Planes if clipping is enabled */
1548         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1549             glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1550             checkGLcall("glClipPlane");
1551         }
1552         glPopMatrix();
1553
1554     } else { /* What was requested!?? */
1555         WARN("invalid matrix specified: %i\n", d3dts);
1556
1557     }
1558
1559     /* Release lock, all done */
1560     LEAVE_GL();
1561     return D3D_OK;
1562
1563 }
1564 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1565     ICOM_THIS(IDirect3DDevice8Impl,iface);
1566     TRACE("(%p) : for State %d\n", This, State);
1567     memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1568     return D3D_OK;
1569 }
1570
1571 HRESULT  WINAPI  IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1572     D3DMATRIX *mat = NULL;
1573     D3DMATRIX temp;
1574
1575     /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1576         but works regardless of recording being on. 
1577         If this is found to be wrong, change to StateBlock.                             */
1578     ICOM_THIS(IDirect3DDevice8Impl,iface);
1579     TRACE("(%p) : For state %u\n", This, State);
1580
1581     if (State < HIGHEST_TRANSFORMSTATE)
1582     {
1583         mat = &This->UpdateStateBlock->transforms[State];
1584     } else {
1585         FIXME("Unhandled transform state!!\n");
1586     }
1587
1588     /* Copied from ddraw code:  */
1589     temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1590     temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1591     temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1592     temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1593
1594     temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1595     temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1596     temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1597     temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1598
1599     temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1600     temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1601     temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1602     temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1603
1604     temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1605     temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1606     temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1607     temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1608
1609     /* Apply change via set transform - will reapply to eg. lights this way */
1610     IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1611     return D3D_OK;
1612 }
1613 HRESULT  WINAPI  IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1614     ICOM_THIS(IDirect3DDevice8Impl,iface);
1615
1616     TRACE("(%p)\n", This);
1617     This->UpdateStateBlock->Changed.viewport = TRUE;
1618     This->UpdateStateBlock->Set.viewport = TRUE;
1619     memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1620
1621     /* Handle recording of state blocks */
1622     if (This->isRecordingState) {
1623         TRACE("Recording... not performing anything\n");
1624         return D3D_OK;
1625     }
1626
1627     ENTER_GL();
1628
1629     TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1630           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1631
1632     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1633     checkGLcall("glDepthRange");
1634     /* Note: GL requires lower left, DirectX supplies upper left */
1635     glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)), 
1636                pViewport->Width, pViewport->Height);
1637     checkGLcall("glViewport");
1638
1639     LEAVE_GL();
1640
1641     return D3D_OK;
1642
1643 }
1644 HRESULT  WINAPI  IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1645     ICOM_THIS(IDirect3DDevice8Impl,iface);
1646     TRACE("(%p)\n", This);
1647     memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1648     return D3D_OK;
1649 }
1650
1651 HRESULT  WINAPI  IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1652     ICOM_THIS(IDirect3DDevice8Impl,iface);
1653
1654     This->UpdateStateBlock->Changed.material = TRUE;
1655     This->UpdateStateBlock->Set.material = TRUE;
1656     memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1657
1658     /* Handle recording of state blocks */
1659     if (This->isRecordingState) {
1660         TRACE("Recording... not performing anything\n");
1661         return D3D_OK;
1662     }
1663
1664     ENTER_GL();
1665     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1666     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1667     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1668     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1669     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1670
1671     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1672     checkGLcall("glMaterialfv");
1673     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1674     checkGLcall("glMaterialfv");
1675
1676     /* Only change material color if specular is enabled, otherwise it is set to black */
1677     if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1678        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1679        checkGLcall("glMaterialfv");
1680     } else {
1681        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1682        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1683        checkGLcall("glMaterialfv");
1684     }
1685     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1686     checkGLcall("glMaterialfv");
1687     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1688     checkGLcall("glMaterialf");
1689
1690     LEAVE_GL();
1691     return D3D_OK;
1692 }
1693 HRESULT  WINAPI  IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1694     ICOM_THIS(IDirect3DDevice8Impl,iface);
1695     memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1696     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1697     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1698     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1699     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1700     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1701     return D3D_OK;
1702 }
1703
1704 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1705    you can reference any indexes you want as long as that number max are enabled are any
1706    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1707    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1708    but when recording, just build a chain pretty much of commands to be replayed.                  */
1709    
1710 HRESULT  WINAPI  IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1711     float rho;
1712     PLIGHTINFOEL *object, *temp;
1713
1714     ICOM_THIS(IDirect3DDevice8Impl,iface);
1715     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1716
1717     /* If recording state block, just add to end of lights chain */
1718     if (This->isRecordingState) {
1719         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1720         if (NULL == object) {
1721             return D3DERR_OUTOFVIDEOMEMORY;
1722         }
1723         memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1724         object->OriginalIndex = Index;
1725         object->glIndex = -1;
1726         object->changed = TRUE;
1727
1728         /* Add to the END of the chain of lights changes to be replayed */
1729         if (This->UpdateStateBlock->lights == NULL) {
1730             This->UpdateStateBlock->lights = object;
1731         } else {
1732             temp = This->UpdateStateBlock->lights;
1733             while (temp->next != NULL) temp=temp->next;
1734             temp->next = object;
1735         }
1736         TRACE("Recording... not performing anything more\n");
1737         return D3D_OK;
1738     }
1739
1740     /* Ok, not recording any longer so do real work */
1741     object = This->StateBlock->lights;
1742     while (object != NULL && object->OriginalIndex != Index) object = object->next;
1743
1744     /* If we didn't find it in the list of lights, time to add it */
1745     if (object == NULL) {
1746         PLIGHTINFOEL *insertAt,*prevPos;
1747
1748         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1749         if (NULL == object) {
1750             return D3DERR_OUTOFVIDEOMEMORY;
1751         }
1752         object->OriginalIndex = Index;
1753         object->glIndex = -1;
1754
1755         /* Add it to the front of list with the idea that lights will be changed as needed 
1756            BUT after any lights currently assigned GL indexes                             */
1757         insertAt = This->StateBlock->lights;
1758         prevPos  = NULL;
1759         while (insertAt != NULL && insertAt->glIndex != -1) {
1760             prevPos  = insertAt;
1761             insertAt = insertAt->next;
1762         }
1763
1764         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1765             This->StateBlock->lights = object;
1766         } else if (insertAt == NULL) { /* End of list */
1767             prevPos->next = object;
1768             object->prev = prevPos;
1769         } else { /* Middle of chain */
1770             if (prevPos == NULL) {
1771                 This->StateBlock->lights = object;
1772             } else {
1773                 prevPos->next = object;
1774             }
1775             object->prev = prevPos;
1776             object->next = insertAt;
1777             insertAt->prev = object;
1778         }
1779     }
1780
1781     /* Initialze the object */
1782     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,
1783           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1784           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1785           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1786     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1787           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1788     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1789
1790     /* Save away the information */
1791     memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1792
1793     switch (pLight->Type) {
1794     case D3DLIGHT_POINT:
1795         /* Position */
1796         object->lightPosn[0] = pLight->Position.x;
1797         object->lightPosn[1] = pLight->Position.y;
1798         object->lightPosn[2] = pLight->Position.z;
1799         object->lightPosn[3] = 1.0f;
1800         object->cutoff = 180.0f;
1801         /* FIXME: Range */
1802         break;
1803
1804     case D3DLIGHT_SPOT:
1805         /* Position */
1806         object->lightPosn[0] = pLight->Position.x;
1807         object->lightPosn[1] = pLight->Position.y;
1808         object->lightPosn[2] = pLight->Position.z;
1809         object->lightPosn[3] = 1.0;
1810
1811         /* Direction */
1812         object->lightDirn[0] = pLight->Direction.x;
1813         object->lightDirn[1] = pLight->Direction.y;
1814         object->lightDirn[2] = pLight->Direction.z;
1815         object->lightDirn[3] = 1.0;
1816
1817         /*
1818          * opengl-ish and d3d-ish spot lights use too different models for the
1819          * light "intensity" as a function of the angle towards the main light direction,
1820          * so we only can approximate very roughly.
1821          * however spot lights are rather rarely used in games (if ever used at all).
1822          * furthermore if still used, probably nobody pays attention to such details.
1823          */
1824         if (pLight->Falloff == 0) {
1825             rho = 6.28f;
1826         } else {
1827             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1828         }
1829         if (rho < 0.0001) rho = 0.0001f;
1830         object->exponent = -0.3/log(cos(rho/2));
1831         object->cutoff = pLight->Phi*90/M_PI;
1832
1833         /* FIXME: Range */
1834         break;
1835
1836     case D3DLIGHT_DIRECTIONAL:
1837         /* Direction */
1838         object->lightPosn[0] = -pLight->Direction.x;
1839         object->lightPosn[1] = -pLight->Direction.y;
1840         object->lightPosn[2] = -pLight->Direction.z;
1841         object->lightPosn[3] = 0.0;
1842         object->exponent     = 0.0f;
1843         object->cutoff       = 180.0f;
1844         break;
1845
1846     default:
1847         FIXME("Unrecognized light type %d\n", pLight->Type);
1848     }
1849
1850     /* Update the live definitions if the light is currently assigned a glIndex */
1851     if (object->glIndex != -1) {
1852         setup_light(iface, object->glIndex, object);
1853     }
1854     return D3D_OK;
1855 }
1856 HRESULT  WINAPI  IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1857     PLIGHTINFOEL *lightInfo = NULL;
1858     ICOM_THIS(IDirect3DDevice8Impl,iface); 
1859     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1860     
1861     /* Locate the light in the live lights */
1862     lightInfo = This->StateBlock->lights;
1863     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1864
1865     if (lightInfo == NULL) {
1866         TRACE("Light information requested but light not defined\n");
1867         return D3DERR_INVALIDCALL;
1868     }
1869
1870     memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1871     return D3D_OK;
1872 }
1873 HRESULT  WINAPI  IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1874     PLIGHTINFOEL *lightInfo = NULL;
1875     ICOM_THIS(IDirect3DDevice8Impl,iface);
1876     TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1877
1878     /* If recording state block, just add to end of lights chain with changedEnable set to true */
1879     if (This->isRecordingState) {
1880         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1881         if (NULL == lightInfo) {
1882             return D3DERR_OUTOFVIDEOMEMORY;
1883         }
1884         lightInfo->OriginalIndex = Index;
1885         lightInfo->glIndex = -1;
1886         lightInfo->enabledChanged = TRUE;
1887
1888         /* Add to the END of the chain of lights changes to be replayed */
1889         if (This->UpdateStateBlock->lights == NULL) {
1890             This->UpdateStateBlock->lights = lightInfo;
1891         } else {
1892             PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1893             while (temp->next != NULL) temp=temp->next;
1894             temp->next = lightInfo;
1895         }
1896         TRACE("Recording... not performing anything more\n");
1897         return D3D_OK;
1898     }
1899
1900     /* Not recording... So, locate the light in the live lights */
1901     lightInfo = This->StateBlock->lights;
1902     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1903
1904     /* Special case - enabling an undefined light creates one with a strict set of parms! */
1905     if (lightInfo == NULL) {
1906         D3DLIGHT8 lightParms;
1907         /* Warning - untested code :-) Prob safe to change fixme to a trace but
1908              wait until someone confirms it seems to work!                     */
1909         TRACE("Light enabled requested but light not defined, so defining one!\n"); 
1910         lightParms.Type = D3DLIGHT_DIRECTIONAL;
1911         lightParms.Diffuse.r = 1.0;
1912         lightParms.Diffuse.g = 1.0;
1913         lightParms.Diffuse.b = 1.0;
1914         lightParms.Diffuse.a = 0.0;
1915         lightParms.Specular.r = 0.0;
1916         lightParms.Specular.g = 0.0;
1917         lightParms.Specular.b = 0.0;
1918         lightParms.Specular.a = 0.0;
1919         lightParms.Ambient.r = 0.0;
1920         lightParms.Ambient.g = 0.0;
1921         lightParms.Ambient.b = 0.0;
1922         lightParms.Ambient.a = 0.0;
1923         lightParms.Position.x = 0.0;
1924         lightParms.Position.y = 0.0;
1925         lightParms.Position.z = 0.0;
1926         lightParms.Direction.x = 0.0;
1927         lightParms.Direction.y = 0.0;
1928         lightParms.Direction.z = 1.0;
1929         lightParms.Range = 0.0;
1930         lightParms.Falloff = 0.0;
1931         lightParms.Attenuation0 = 0.0;
1932         lightParms.Attenuation1 = 0.0;
1933         lightParms.Attenuation2 = 0.0;
1934         lightParms.Theta = 0.0;
1935         lightParms.Phi = 0.0;
1936         IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1937
1938         /* Search for it again! Should be fairly quick as near head of list */
1939         lightInfo = This->StateBlock->lights;
1940         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1941         if (lightInfo == NULL) {
1942             FIXME("Adding default lights has failed dismally\n");
1943             return D3DERR_INVALIDCALL;
1944         }
1945     }
1946
1947     /* OK, we now have a light... */
1948     if (Enable == FALSE) {
1949
1950         /* If we are disabling it, check it was enabled, and
1951            still only do something if it has assigned a glIndex (which it should have!)   */
1952         if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1953             TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1954             ENTER_GL();
1955             glDisable(GL_LIGHT0 + lightInfo->glIndex);
1956             checkGLcall("glDisable GL_LIGHT0+Index");
1957             LEAVE_GL();
1958         } else {
1959             TRACE("Nothing to do as light was not enabled\n");
1960         }
1961         lightInfo->lightEnabled = FALSE;
1962     } else {
1963
1964         /* We are enabling it. If it is enabled, its really simple */
1965         if (lightInfo->lightEnabled == TRUE) {
1966             /* nop */
1967             TRACE("Nothing to do as light was enabled\n");
1968
1969         /* If it already has a glIndex, its still simple */
1970         } else if (lightInfo->glIndex != -1) {
1971             TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1972             lightInfo->lightEnabled = TRUE;
1973             ENTER_GL();
1974             glEnable(GL_LIGHT0 + lightInfo->glIndex);
1975             checkGLcall("glEnable GL_LIGHT0+Index already setup");
1976             LEAVE_GL();
1977
1978         /* Otherwise got to find space - lights are ordered gl indexes first */
1979         } else {
1980             PLIGHTINFOEL *bsf  = NULL;
1981             PLIGHTINFOEL *pos  = This->StateBlock->lights;
1982             PLIGHTINFOEL *prev = NULL;
1983             int           Index= 0;
1984             int           glIndex = -1;
1985
1986             /* Try to minimize changes as much as possible */
1987             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1988
1989                 /* Try to remember which index can be replaced if necessary */
1990                 if (bsf==NULL && pos->lightEnabled == FALSE) {
1991                     /* Found a light we can replace, save as best replacement */
1992                     bsf = pos;
1993                 }
1994
1995                 /* Step to next space */
1996                 prev = pos;
1997                 pos = pos->next;
1998                 Index ++;
1999             }
2000
2001             /* If we have too many active lights, fail the call */
2002             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2003                 FIXME("Program requests too many concurrent lights\n");
2004                 return D3DERR_INVALIDCALL;
2005
2006             /* If we have allocated all lights, but not all are enabled,
2007                reuse one which is not enabled                           */
2008             } else if (Index == This->maxConcurrentLights) {
2009                 /* use bsf - Simply swap the new light and the BSF one */
2010                 PLIGHTINFOEL *bsfNext = bsf->next;
2011                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2012
2013                 /* Sort out ends */
2014                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2015                 if (bsf->prev != NULL) {
2016                     bsf->prev->next = lightInfo;
2017                 } else {
2018                     This->StateBlock->lights = lightInfo;
2019                 }
2020
2021                 /* If not side by side, lots of chains to update */
2022                 if (bsf->next != lightInfo) {
2023                     lightInfo->prev->next = bsf;
2024                     bsf->next->prev = lightInfo;
2025                     bsf->next       = lightInfo->next;
2026                     bsf->prev       = lightInfo->prev;
2027                     lightInfo->next = bsfNext;
2028                     lightInfo->prev = bsfPrev;
2029
2030                 } else {
2031                     /* Simple swaps */
2032                     bsf->prev = lightInfo;
2033                     bsf->next = lightInfo->next;
2034                     lightInfo->next = bsf;
2035                     lightInfo->prev = bsfPrev;
2036                 }
2037
2038
2039                 /* Update states */
2040                 glIndex = bsf->glIndex;
2041                 bsf->glIndex = -1;
2042                 lightInfo->glIndex = glIndex;
2043                 lightInfo->lightEnabled = TRUE;
2044
2045                 /* Finally set up the light in gl itself */
2046                 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2047                 ENTER_GL();
2048                 setup_light(iface, glIndex, lightInfo);
2049                 glEnable(GL_LIGHT0 + glIndex);
2050                 checkGLcall("glEnable GL_LIGHT0 new setup");
2051                 LEAVE_GL();
2052
2053             /* If we reached the end of the allocated lights, with space in the
2054                gl lights, setup a new light                                     */
2055             } else if (pos->glIndex == -1) {
2056
2057                 /* We reached the end of the allocated gl lights, so already 
2058                     know the index of the next one!                          */
2059                 glIndex = Index;
2060                 lightInfo->glIndex = glIndex;
2061                 lightInfo->lightEnabled = TRUE;
2062
2063                 /* In an ideal world, its already in the right place */
2064                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2065                    /* No need to move it */
2066                 } else {
2067                     /* Remove this light from the list */
2068                     lightInfo->prev->next = lightInfo->next;
2069                     if (lightInfo->next != NULL) {
2070                         lightInfo->next->prev = lightInfo->prev;
2071                     }
2072
2073                     /* Add in at appropriate place (inbetween prev and pos) */
2074                     lightInfo->prev = prev;
2075                     lightInfo->next = pos;
2076                     if (prev == NULL) {
2077                         This->StateBlock->lights = lightInfo;
2078                     } else {
2079                         prev->next = lightInfo;
2080                     }
2081                     if (pos != NULL) {
2082                         pos->prev = lightInfo;
2083                     }
2084                 }
2085
2086                 /* Finally set up the light in gl itself */
2087                 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2088                 ENTER_GL();
2089                 setup_light(iface, glIndex, lightInfo);
2090                 glEnable(GL_LIGHT0 + glIndex);
2091                 checkGLcall("glEnable GL_LIGHT0 new setup");
2092                 LEAVE_GL();
2093                 
2094             }
2095         }
2096     }
2097     return D3D_OK;
2098 }
2099 HRESULT  WINAPI  IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2100
2101     PLIGHTINFOEL *lightInfo = NULL;
2102     ICOM_THIS(IDirect3DDevice8Impl,iface); 
2103     TRACE("(%p) : for idx(%ld)\n", This, Index);
2104     
2105     /* Locate the light in the live lights */
2106     lightInfo = This->StateBlock->lights;
2107     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2108
2109     if (lightInfo == NULL) {
2110         TRACE("Light enabled state requested but light not defined\n");
2111         return D3DERR_INVALIDCALL;
2112     }
2113     *pEnable = lightInfo->lightEnabled;
2114     return D3D_OK;
2115 }
2116 HRESULT  WINAPI  IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2117     ICOM_THIS(IDirect3DDevice8Impl,iface);
2118     TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2119
2120     /* Validate Index */
2121     if (Index >= GL_LIMITS(clipplanes)) {
2122         TRACE("Application has requested clipplane this device doesn't support\n");
2123         return D3DERR_INVALIDCALL;
2124     }
2125
2126     This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2127     This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2128     This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2129     This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2130     This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2131     This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2132
2133     /* Handle recording of state blocks */
2134     if (This->isRecordingState) {
2135         TRACE("Recording... not performing anything\n");
2136         return D3D_OK;
2137     }
2138
2139     /* Apply it */
2140
2141     ENTER_GL();
2142
2143     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2144     glMatrixMode(GL_MODELVIEW);
2145     glPushMatrix();
2146     glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2147
2148     TRACE("Clipplane [%f,%f,%f,%f]\n", 
2149           This->UpdateStateBlock->clipplane[Index][0], 
2150           This->UpdateStateBlock->clipplane[Index][1],
2151           This->UpdateStateBlock->clipplane[Index][2], 
2152           This->UpdateStateBlock->clipplane[Index][3]);
2153     glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2154     checkGLcall("glClipPlane");
2155
2156     glPopMatrix();
2157
2158     LEAVE_GL();
2159
2160     return D3D_OK;
2161 }
2162 HRESULT  WINAPI  IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2163     ICOM_THIS(IDirect3DDevice8Impl,iface);
2164     TRACE("(%p) : for idx %ld\n", This, Index);
2165
2166     /* Validate Index */
2167     if (Index >= GL_LIMITS(clipplanes)) {
2168         TRACE("Application has requested clipplane this device doesn't support\n");
2169         return D3DERR_INVALIDCALL;
2170     }
2171
2172     pPlane[0] = This->StateBlock->clipplane[Index][0];
2173     pPlane[1] = This->StateBlock->clipplane[Index][1];
2174     pPlane[2] = This->StateBlock->clipplane[Index][2];
2175     pPlane[3] = This->StateBlock->clipplane[Index][3];
2176     return D3D_OK;
2177 }
2178 HRESULT  WINAPI  IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2179     ICOM_THIS(IDirect3DDevice8Impl,iface);
2180     DWORD OldValue = This->StateBlock->renderstate[State];
2181         
2182     TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2183     This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2184     This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2185     This->UpdateStateBlock->renderstate[State] = Value;
2186
2187     /* Handle recording of state blocks */
2188     if (This->isRecordingState) {
2189         TRACE("Recording... not performing anything\n");
2190         return D3D_OK;
2191     }
2192
2193     ENTER_GL();
2194
2195     switch (State) {
2196     case D3DRS_FILLMODE                  :
2197         switch ((D3DFILLMODE) Value) {
2198         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2199         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2200         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2201         default:
2202             FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2203         }
2204         checkGLcall("glPolygonMode (fillmode)");
2205         break;
2206
2207     case D3DRS_LIGHTING                  :
2208         if (Value) {
2209             glEnable(GL_LIGHTING);
2210             checkGLcall("glEnable GL_LIGHTING");
2211         } else {
2212             glDisable(GL_LIGHTING);
2213             checkGLcall("glDisable GL_LIGHTING");
2214         }
2215         break;
2216
2217     case D3DRS_ZENABLE                   :
2218         switch ((D3DZBUFFERTYPE) Value) {
2219         case D3DZB_FALSE:
2220             glDisable(GL_DEPTH_TEST);
2221             checkGLcall("glDisable GL_DEPTH_TEST");
2222             break;
2223         case D3DZB_TRUE:
2224             glEnable(GL_DEPTH_TEST);
2225             checkGLcall("glEnable GL_DEPTH_TEST");
2226             break;
2227
2228         case D3DZB_USEW:
2229         default:
2230             FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2231         }
2232         break;
2233
2234     case D3DRS_CULLMODE                  :
2235
2236         /* If we are culling "back faces with clockwise vertices" then
2237            set front faces to be counter clockwise and enable culling  
2238            of back faces                                               */
2239         switch ((D3DCULL) Value) {
2240         case D3DCULL_NONE:
2241             glDisable(GL_CULL_FACE);
2242             checkGLcall("glDisable GL_CULL_FACE");
2243             break;
2244         case D3DCULL_CW:
2245             glEnable(GL_CULL_FACE);
2246             checkGLcall("glEnable GL_CULL_FACE");
2247             glFrontFace(GL_CCW);
2248             checkGLcall("glFrontFace GL_CCW");
2249             glCullFace(GL_BACK);
2250             break;
2251         case D3DCULL_CCW:
2252             glEnable(GL_CULL_FACE);
2253             checkGLcall("glEnable GL_CULL_FACE");
2254             glFrontFace(GL_CW); 
2255             checkGLcall("glFrontFace GL_CW");
2256             glCullFace(GL_BACK);
2257             break;
2258         default:
2259             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2260         }
2261         break;
2262
2263     case D3DRS_SHADEMODE                 :
2264         switch ((D3DSHADEMODE) Value) {
2265         case D3DSHADE_FLAT:
2266             glShadeModel(GL_FLAT);
2267             checkGLcall("glShadeModel");
2268             break;
2269         case D3DSHADE_GOURAUD:
2270             glShadeModel(GL_SMOOTH);
2271             checkGLcall("glShadeModel");
2272             break;
2273         case D3DSHADE_PHONG:
2274             FIXME("D3DSHADE_PHONG isn't supported?\n");
2275
2276             LEAVE_GL();
2277             return D3DERR_INVALIDCALL;
2278         default:
2279             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2280         }
2281         break;
2282
2283     case D3DRS_DITHERENABLE              :
2284         if (Value) {
2285             glEnable(GL_DITHER);
2286             checkGLcall("glEnable GL_DITHER");
2287         } else {
2288             glDisable(GL_DITHER);
2289             checkGLcall("glDisable GL_DITHER");
2290         }
2291         break;
2292
2293     case D3DRS_ZWRITEENABLE              :
2294         if (Value) {
2295             glDepthMask(1);
2296             checkGLcall("glDepthMask");
2297         } else {
2298             glDepthMask(0);
2299             checkGLcall("glDepthMask");
2300         }
2301         break;
2302
2303     case D3DRS_ZFUNC                     :
2304         {
2305             int glParm = GL_LESS;
2306
2307             switch ((D3DCMPFUNC) Value) {
2308             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2309             case D3DCMP_LESS:          glParm=GL_LESS; break;
2310             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2311             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2312             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2313             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2314             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2315             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2316             default:
2317                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2318             }
2319             glDepthFunc(glParm);
2320             checkGLcall("glDepthFunc");
2321         }
2322         break;
2323
2324     case D3DRS_AMBIENT                   :
2325         {
2326             float col[4];
2327             D3DCOLORTOGLFLOAT4(Value, col);
2328             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2329             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2330             checkGLcall("glLightModel for MODEL_AMBIENT");
2331
2332         }
2333         break;
2334
2335     case D3DRS_ALPHABLENDENABLE          :
2336         if (Value) {
2337             glEnable(GL_BLEND);
2338             checkGLcall("glEnable GL_BLEND");
2339         } else {
2340             glDisable(GL_BLEND);
2341             checkGLcall("glDisable GL_BLEND");
2342         };
2343         break;
2344
2345     case D3DRS_SRCBLEND                  :
2346     case D3DRS_DESTBLEND                 :
2347         {
2348             int newVal = GL_ZERO;
2349             switch (Value) {
2350             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
2351             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
2352             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
2353             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
2354             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
2355             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
2356             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
2357             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
2358             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
2359             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
2360             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
2361
2362             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
2363                 This->srcBlend = newVal;
2364                 This->dstBlend = newVal;
2365                 break;
2366
2367             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
2368                 This->srcBlend = newVal;
2369                 This->dstBlend = newVal;
2370                 break;
2371             default:
2372                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2373             }
2374
2375             if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2376             if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2377             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2378             glBlendFunc(This->srcBlend, This->dstBlend);
2379
2380             checkGLcall("glBlendFunc");
2381         }
2382         break;
2383
2384     case D3DRS_ALPHATESTENABLE           :
2385         if (Value) {
2386             glEnable(GL_ALPHA_TEST);
2387             checkGLcall("glEnable GL_ALPHA_TEST");
2388         } else {
2389             glDisable(GL_ALPHA_TEST);
2390             checkGLcall("glDisable GL_ALPHA_TEST");
2391         }
2392         break;
2393
2394     case D3DRS_ALPHAFUNC                 :
2395         {
2396             int glParm = GL_LESS;
2397             float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2398
2399             switch ((D3DCMPFUNC) Value) {
2400             case D3DCMP_NEVER:         glParm = GL_NEVER; break;
2401             case D3DCMP_LESS:          glParm = GL_LESS; break;
2402             case D3DCMP_EQUAL:         glParm = GL_EQUAL; break;
2403             case D3DCMP_LESSEQUAL:     glParm = GL_LEQUAL; break;
2404             case D3DCMP_GREATER:       glParm = GL_GREATER; break;
2405             case D3DCMP_NOTEQUAL:      glParm = GL_NOTEQUAL; break;
2406             case D3DCMP_GREATEREQUAL:  glParm = GL_GEQUAL; break;
2407             case D3DCMP_ALWAYS:        glParm = GL_ALWAYS; break;
2408             default:
2409                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2410             }
2411             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2412             glAlphaFunc(glParm, ref);
2413             This->alphafunc = glParm;
2414             checkGLcall("glAlphaFunc");
2415         }
2416         break;
2417
2418     case D3DRS_ALPHAREF                  :
2419         {
2420             int glParm = This->alphafunc;
2421             float ref = 1.0f;
2422
2423             ref = ((float) Value) / 255.0f;
2424             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2425             glAlphaFunc(glParm, ref);
2426             checkGLcall("glAlphaFunc");
2427         }
2428         break;
2429
2430     case D3DRS_CLIPPLANEENABLE           :
2431     case D3DRS_CLIPPING                  :
2432         {
2433             /* Ensure we only do the changed clip planes */
2434             DWORD enable  = 0xFFFFFFFF;
2435             DWORD disable = 0x00000000;
2436             
2437             /* If enabling / disabling all */
2438             if (State == D3DRS_CLIPPING) {
2439                 if (Value) {
2440                     enable  = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2441                     disable = 0x00;
2442                 } else {
2443                     disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2444                     enable  = 0x00;
2445                 }
2446             } else {
2447                 enable =   Value & ~OldValue;
2448                 disable = ~Value &  OldValue;
2449             }
2450             
2451             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
2452             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
2453             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
2454             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
2455             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
2456             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
2457             
2458             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2459             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2460             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2461             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2462             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2463             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2464         }
2465         break;
2466
2467     case D3DRS_BLENDOP                   :
2468         {
2469             int glParm = GL_FUNC_ADD;
2470
2471             switch ((D3DBLENDOP) Value) {
2472             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
2473             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
2474             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2475             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
2476             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
2477             default:
2478                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2479             }
2480             TRACE("glBlendEquation(%x)\n", glParm);
2481             glBlendEquation(glParm);
2482             checkGLcall("glBlendEquation");
2483         }
2484         break;
2485
2486     case D3DRS_TEXTUREFACTOR             :
2487         {
2488             int i;
2489
2490             /* Note the texture color applies to all textures whereas 
2491                GL_TEXTURE_ENV_COLOR applies to active only */
2492             float col[4];
2493             D3DCOLORTOGLFLOAT4(Value, col);
2494             /* Set the default alpha blend color */
2495             glBlendColor(col[0], col[1], col[2], col[3]);
2496             checkGLcall("glBlendColor");
2497
2498             /* And now the default texture color as well */
2499             for (i = 0; i < GL_LIMITS(textures); i++) {
2500
2501                 /* Note the D3DRS value applies to all textures, but GL has one
2502                    per texture, so apply it now ready to be used!               */
2503                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2504 #if defined(GL_VERSION_1_3)
2505                     glActiveTexture(GL_TEXTURE0 + i);
2506 #else
2507                     glActiveTextureARB(GL_TEXTURE0_ARB + i);
2508 #endif
2509                     checkGLcall("Activate texture.. to update const color");
2510                 } else if (i>0) {
2511                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2512                 }
2513
2514                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2515                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2516             }
2517         }
2518         break;
2519
2520     case D3DRS_SPECULARENABLE            : 
2521         {
2522             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2523                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2524                specular color. This is wrong:
2525                Separate specular color means the specular colour is maintained separately, whereas
2526                single color means it is merged in. However in both cases they are being used to
2527                some extent.
2528                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2529                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2530                   running 1.4 yet!
2531              */
2532               if (Value) {
2533                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2534                 checkGLcall("glMaterialfv");
2535                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2536                   glEnable(GL_COLOR_SUM_EXT);
2537                 } else {
2538                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
2539                 }
2540                 checkGLcall("glEnable(GL_COLOR_SUM)");
2541               } else {
2542                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2543
2544                 /* for the case of enabled lighting: */
2545                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2546                 checkGLcall("glMaterialfv");
2547
2548                 /* for the case of disabled lighting: */
2549                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2550                   glDisable(GL_COLOR_SUM_EXT);
2551                 } else {
2552                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
2553                 }
2554                 checkGLcall("glDisable(GL_COLOR_SUM)");
2555               }
2556         }
2557         break;
2558
2559     case D3DRS_STENCILENABLE             :
2560         if (Value) {
2561             glEnable(GL_STENCIL_TEST);
2562             checkGLcall("glEnable GL_STENCIL_TEST");
2563         } else {
2564             glDisable(GL_STENCIL_TEST);
2565             checkGLcall("glDisable GL_STENCIL_TEST");
2566         }
2567         break;
2568
2569     case D3DRS_STENCILFUNC               :
2570         {
2571            int glParm = GL_ALWAYS;
2572            int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2573            GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2574
2575            switch ((D3DCMPFUNC) Value) {
2576            case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2577            case D3DCMP_LESS:          glParm=GL_LESS; break;
2578            case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2579            case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2580            case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2581            case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2582            case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2583            case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2584            default:
2585                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2586            }
2587            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2588            This->stencilfunc = glParm;
2589            glStencilFunc(glParm, ref, mask);
2590            checkGLcall("glStencilFunc");
2591         }
2592         break;
2593
2594     case D3DRS_STENCILREF                :
2595         {
2596            int glParm = This->stencilfunc;
2597            int ref = 0;
2598            GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2599
2600            ref = Value;
2601            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2602            glStencilFunc(glParm, ref, mask);
2603            checkGLcall("glStencilFunc");
2604         }
2605         break;
2606
2607     case D3DRS_STENCILMASK               :
2608         {
2609            int glParm = This->stencilfunc;
2610            int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2611            GLuint mask = Value;
2612
2613            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2614            glStencilFunc(glParm, ref, mask);
2615            checkGLcall("glStencilFunc");
2616         }
2617         break;
2618
2619     case D3DRS_STENCILFAIL               :
2620         {
2621             GLenum fail  ; 
2622             GLenum zpass ; 
2623             GLenum zfail ; 
2624
2625             fail = StencilOp(Value);
2626             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2627             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2628             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2629             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2630
2631             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2632             glStencilOp(fail, zfail, zpass);
2633             checkGLcall("glStencilOp(fail, zfail, zpass);");
2634         }
2635         break;
2636     case D3DRS_STENCILZFAIL              :
2637         {
2638             GLenum fail  ; 
2639             GLenum zpass ; 
2640             GLenum zfail ; 
2641
2642             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2643             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2644             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2645             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2646             zfail = StencilOp(Value);
2647
2648             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2649             glStencilOp(fail, zfail, zpass);
2650             checkGLcall("glStencilOp(fail, zfail, zpass);");
2651         }
2652         break;
2653     case D3DRS_STENCILPASS               :
2654         {
2655             GLenum fail  ; 
2656             GLenum zpass ; 
2657             GLenum zfail ; 
2658
2659             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2660             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2661             zpass = StencilOp(Value);
2662             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2663             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2664
2665             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2666             glStencilOp(fail, zfail, zpass);
2667             checkGLcall("glStencilOp(fail, zfail, zpass);");
2668         }
2669         break;
2670
2671     case D3DRS_STENCILWRITEMASK          :
2672         {
2673             glStencilMask(Value);
2674             TRACE("glStencilMask(%lu)\n", Value);
2675             checkGLcall("glStencilMask");
2676         }
2677         break;
2678
2679     case D3DRS_FOGENABLE                 :
2680         {
2681             if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2682                glEnable(GL_FOG);
2683                checkGLcall("glEnable GL_FOG");
2684             } else {
2685                glDisable(GL_FOG);
2686                checkGLcall("glDisable GL_FOG");
2687             }
2688         }
2689         break;
2690
2691     case D3DRS_FOGCOLOR                  :
2692         {
2693             float col[4];
2694             D3DCOLORTOGLFLOAT4(Value, col);
2695             /* Set the default alpha blend color */
2696             glFogfv(GL_FOG_COLOR, &col[0]);
2697             checkGLcall("glFog GL_FOG_COLOR");
2698         }
2699         break;
2700
2701     case D3DRS_FOGTABLEMODE              :
2702         {
2703           switch (Value) {
2704           case D3DFOG_NONE:    /* I don't know what to do here */ break;
2705           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2706           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2707           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2708           default:
2709             FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2710           }
2711         }
2712         break;
2713
2714     case D3DRS_FOGSTART                  :
2715         {
2716             float *f = (float*) &Value;
2717             glFogfv(GL_FOG_START, f);
2718             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2719             TRACE("Fog Start == %f\n", *f);
2720         }
2721         break;
2722
2723     case D3DRS_FOGEND                    :
2724         {
2725             float *f = (float*) &Value;
2726             glFogfv(GL_FOG_END, f);
2727             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2728             TRACE("Fog End == %f\n", *f);
2729         }
2730         break;
2731
2732     case D3DRS_FOGDENSITY                :
2733         {
2734             float *f = (float*) &Value;
2735             glFogfv(GL_FOG_DENSITY, f);
2736             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2737         }
2738         break;
2739
2740     case D3DRS_VERTEXBLEND               :
2741         {
2742           This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2743           TRACE("Vertex Blending state to %ld\n",  Value);
2744         }
2745         break;
2746
2747     case D3DRS_TWEENFACTOR               :
2748         {
2749           This->UpdateStateBlock->tween_factor = *((float*) &Value);
2750           TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2751         }
2752         break;
2753
2754     case D3DRS_INDEXEDVERTEXBLENDENABLE  :
2755         {
2756           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2757         }
2758         break;
2759
2760     case D3DRS_COLORVERTEX               :
2761     case D3DRS_DIFFUSEMATERIALSOURCE     :
2762     case D3DRS_SPECULARMATERIALSOURCE    :
2763     case D3DRS_AMBIENTMATERIALSOURCE     :
2764     case D3DRS_EMISSIVEMATERIALSOURCE    :
2765         {
2766             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2767
2768             if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2769                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2770                       This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2771                       This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2772                       This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2773                       This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2774
2775                 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2776                     if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2777                         Parm = GL_AMBIENT_AND_DIFFUSE;
2778                     } else {
2779                         Parm = GL_DIFFUSE;
2780                     }
2781                 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2782                     Parm = GL_AMBIENT;
2783                 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2784                     Parm = GL_EMISSION;
2785                 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2786                     Parm = GL_SPECULAR;
2787                 } else {
2788                     Parm = -1;
2789                 }
2790
2791                 if (Parm == -1) {
2792                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2793                 } else {
2794                     This->tracking_color = NEEDS_TRACKING;
2795                     This->tracking_parm  = Parm;
2796                 }
2797
2798             } else {
2799                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2800             }
2801         }
2802         break; 
2803
2804     case D3DRS_LINEPATTERN               :
2805         {
2806             D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2807             TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2808
2809             if (pattern->wRepeatFactor) {
2810                 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2811                 checkGLcall("glLineStipple(repeat, linepattern)");
2812                 glEnable(GL_LINE_STIPPLE);
2813                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2814             } else {
2815                 glDisable(GL_LINE_STIPPLE);
2816                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2817             }
2818         }
2819         break;
2820
2821     case D3DRS_ZBIAS                     :
2822         {
2823             if (Value) {
2824                 TRACE("ZBias value %f\n", *((float*)&Value));
2825                 glPolygonOffset(0, -*((float*)&Value));
2826                 checkGLcall("glPolygonOffset(0, -Value)");
2827                 glEnable(GL_POLYGON_OFFSET_FILL);
2828                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2829                 glEnable(GL_POLYGON_OFFSET_LINE);
2830                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2831                 glEnable(GL_POLYGON_OFFSET_POINT);
2832                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2833             } else {
2834                 glDisable(GL_POLYGON_OFFSET_FILL);
2835                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2836                 glDisable(GL_POLYGON_OFFSET_LINE);
2837                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2838                 glDisable(GL_POLYGON_OFFSET_POINT);
2839                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2840             }
2841         }
2842         break;
2843
2844     case D3DRS_NORMALIZENORMALS          :
2845         if (Value) {
2846             glEnable(GL_NORMALIZE);
2847             checkGLcall("glEnable(GL_NORMALIZE);");
2848         } else {
2849             glDisable(GL_NORMALIZE);
2850             checkGLcall("glDisable(GL_NORMALIZE);");
2851         }
2852         break;
2853
2854     case D3DRS_POINTSIZE                 :
2855         TRACE("Set point size to %f\n", *((float*)&Value));
2856         glPointSize(*((float*)&Value));
2857         checkGLcall("glPointSize(...);");
2858         break;
2859
2860     case D3DRS_POINTSIZE_MIN             :
2861         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2862           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2863           checkGLcall("glPointParameterfEXT(...);");
2864         } else {
2865           FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2866         }
2867         break;
2868
2869     case D3DRS_POINTSIZE_MAX             :
2870         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2871           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2872           checkGLcall("glPointParameterfEXT(...);");
2873         } else {
2874           FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2875         }
2876         break;
2877
2878     case D3DRS_POINTSCALE_A              :
2879     case D3DRS_POINTSCALE_B              :
2880     case D3DRS_POINTSCALE_C              :
2881     case D3DRS_POINTSCALEENABLE          :
2882         {
2883             /* If enabled, supply the parameters, otherwise fall back to defaults */
2884             if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2885                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2886                 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2887                 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2888                 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2889
2890                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2891                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2892                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2893                 } else {
2894                   TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2895                 }
2896             } else {
2897                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2898                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2899                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2900                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2901                 } else {
2902                   TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2903                 }
2904             }
2905             break;
2906         }
2907
2908     case D3DRS_COLORWRITEENABLE          :
2909         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n", 
2910               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
2911               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2912               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
2913               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0); 
2914         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE, 
2915                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2916                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE, 
2917                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2918         checkGLcall("glColorMask(...)");
2919                 break;
2920
2921         /* Unhandled yet...! */
2922     case D3DRS_LASTPIXEL                 :
2923     case D3DRS_ZVISIBLE                  :
2924     case D3DRS_EDGEANTIALIAS             :
2925     case D3DRS_RANGEFOGENABLE            :
2926     case D3DRS_WRAP0                     :
2927     case D3DRS_WRAP1                     :
2928     case D3DRS_WRAP2                     :
2929     case D3DRS_WRAP3                     :
2930     case D3DRS_WRAP4                     :
2931     case D3DRS_WRAP5                     :
2932     case D3DRS_WRAP6                     :
2933     case D3DRS_WRAP7                     :
2934     case D3DRS_FOGVERTEXMODE             :
2935     case D3DRS_LOCALVIEWER               :
2936     case D3DRS_SOFTWAREVERTEXPROCESSING  :
2937     case D3DRS_POINTSPRITEENABLE         :
2938     case D3DRS_MULTISAMPLEANTIALIAS      :
2939     case D3DRS_MULTISAMPLEMASK           :
2940     case D3DRS_PATCHEDGESTYLE            :
2941     case D3DRS_PATCHSEGMENTS             :
2942     case D3DRS_DEBUGMONITORTOKEN         :
2943     case D3DRS_POSITIONORDER             :
2944     case D3DRS_NORMALORDER               :
2945         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2946         TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2947         break;
2948     default:
2949         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2950     }
2951
2952     LEAVE_GL();
2953
2954     return D3D_OK;
2955 }
2956 HRESULT  WINAPI  IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2957     ICOM_THIS(IDirect3DDevice8Impl,iface);
2958     TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2959     *pValue = This->StateBlock->renderstate[State];
2960     return D3D_OK;
2961 }
2962 HRESULT  WINAPI  IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2963   ICOM_THIS(IDirect3DDevice8Impl,iface);
2964   
2965   TRACE("(%p)\n", This);
2966   
2967   return IDirect3DDeviceImpl_BeginStateBlock(This);
2968 }
2969 HRESULT  WINAPI  IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2970   IDirect3DStateBlockImpl* pSB;
2971   ICOM_THIS(IDirect3DDevice8Impl,iface);
2972   HRESULT res;
2973
2974   TRACE("(%p)\n", This);
2975
2976   res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2977   *pToken = (DWORD) pSB;
2978   return res;
2979 }
2980
2981 HRESULT  WINAPI  IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2982   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2983   ICOM_THIS(IDirect3DDevice8Impl,iface);
2984
2985   TRACE("(%p)\n", This);
2986
2987   return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2988
2989 }
2990 HRESULT  WINAPI  IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2991   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2992   ICOM_THIS(IDirect3DDevice8Impl,iface);
2993
2994   TRACE("(%p)\n", This);
2995
2996   return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2997 }
2998 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2999   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3000   ICOM_THIS(IDirect3DDevice8Impl,iface);
3001
3002   TRACE("(%p)\n", This);
3003
3004   return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3005 }
3006
3007 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3008   IDirect3DStateBlockImpl* pSB;
3009   ICOM_THIS(IDirect3DDevice8Impl,iface);
3010   HRESULT res;
3011
3012   TRACE("(%p) : for type %d\n", This, Type);
3013
3014   res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3015   *pToken = (DWORD) pSB;
3016   return res;
3017 }
3018
3019 HRESULT  WINAPI  IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3020     ICOM_THIS(IDirect3DDevice8Impl,iface);
3021     FIXME("(%p) : stub\n", This);    return D3D_OK;
3022 }
3023 HRESULT  WINAPI  IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3024     ICOM_THIS(IDirect3DDevice8Impl,iface);
3025     FIXME("(%p) : stub\n", This);    return D3D_OK;
3026 }
3027 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3028     ICOM_THIS(IDirect3DDevice8Impl,iface);
3029     TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3030     *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3031     if (*ppTexture)
3032         IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3033     return D3D_OK;
3034 }
3035 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3036
3037     IDirect3DBaseTexture8 *oldTxt;
3038     BOOL reapplyStates = TRUE;
3039     DWORD oldTextureDimensions = -1;
3040     DWORD reapplyFlags = 0;
3041
3042     ICOM_THIS(IDirect3DDevice8Impl,iface);
3043     D3DRESOURCETYPE textureType;
3044
3045     oldTxt = This->UpdateStateBlock->textures[Stage];
3046     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3047
3048     /* Reject invalid texture units */
3049     if (Stage >= GL_LIMITS(textures)) {
3050         TRACE("Attempt to access invalid texture rejected\n");
3051         return D3DERR_INVALIDCALL;
3052     }
3053
3054     This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3055     This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3056     This->UpdateStateBlock->textures[Stage] = pTexture;
3057
3058     /* Handle recording of state blocks */
3059     if (This->isRecordingState) {
3060         TRACE("Recording... not performing anything\n");
3061         return D3D_OK;
3062     }
3063
3064     oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3065     ENTER_GL();
3066
3067     /* Make appropriate texture active */
3068     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3069 #if defined(GL_VERSION_1_3)
3070         glActiveTexture(GL_TEXTURE0 + Stage);
3071 #else
3072         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3073 #endif
3074         checkGLcall("glActiveTextureARB");
3075     } else if (Stage>0) {
3076         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3077     }
3078
3079     /* Decrement the count of the previous texture */
3080     if (NULL != oldTxt) {
3081         IDirect3DBaseTexture8Impl_Release(oldTxt);
3082     }
3083
3084     if (NULL != pTexture) {
3085         IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3086
3087         /* Now setup the texture appropraitly */
3088         textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3089
3090         if (textureType == D3DRTYPE_TEXTURE) {
3091           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3092             TRACE("Skipping setting texture as old == new\n");
3093             reapplyStates = FALSE;
3094           } else {
3095             /* Standard 2D texture */
3096             TRACE("Standard 2d texture\n");
3097             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3098
3099             /* Load up the texture now */
3100             IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3101           }
3102         } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3103           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3104             TRACE("Skipping setting texture as old == new\n");
3105             reapplyStates = FALSE;
3106           } else {
3107             /* Standard 3D (volume) texture */
3108             TRACE("Standard 3d texture\n");
3109             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3110
3111             /* Load up the texture now */
3112             IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3113           }
3114         } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3115           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3116             TRACE("Skipping setting texture as old == new\n");
3117             reapplyStates = FALSE;
3118           } else {
3119             /* Standard Cube texture */
3120             TRACE("Standard Cube texture\n");
3121             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3122
3123             /* Load up the texture now */
3124             IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3125           }
3126         } else {
3127             FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3128         }
3129     } else {
3130         TRACE("Setting to no texture (ie default texture)\n");
3131         This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3132         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3133         checkGLcall("glBindTexture");
3134         TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3135     }
3136
3137     /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3138     if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3139        glDisable(oldTextureDimensions);
3140        checkGLcall("Disable oldTextureDimensions");
3141        if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3142           glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3143           checkGLcall("glEnable new texture dimensions");
3144        }
3145
3146        /* If Alpha arg1 is texture then handle the special case when there changes between a
3147           texture and no texture - See comments in set_tex_op                                  */
3148        if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) && 
3149            (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3150        {
3151            reapplyFlags |= REAPPLY_ALPHAOP;
3152        }
3153     }
3154
3155
3156     /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3157        a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3158     if (reapplyStates) {
3159        setupTextureStates(iface, Stage, reapplyFlags);
3160     }
3161
3162     LEAVE_GL();   
3163
3164     return D3D_OK;
3165 }
3166
3167 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3168     ICOM_THIS(IDirect3DDevice8Impl,iface);
3169     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3170     *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3171     return D3D_OK;
3172 }
3173
3174 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3175     ICOM_THIS(IDirect3DDevice8Impl,iface);
3176
3177     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3178    
3179     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3180
3181     /* Reject invalid texture units */
3182     if (Stage >= GL_LIMITS(textures)) {
3183         TRACE("Attempt to access invalid texture rejected\n");
3184         return D3DERR_INVALIDCALL;
3185     }
3186
3187     This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3188     This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3189     This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3190
3191     /* Handle recording of state blocks */
3192     if (This->isRecordingState) {
3193         TRACE("Recording... not performing anything\n");
3194         return D3D_OK;
3195     }
3196
3197     ENTER_GL();
3198
3199     /* Make appropriate texture active */
3200     VTRACE(("Activating appropriate texture state %ld\n", Stage));
3201     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3202 #if defined(GL_VERSION_1_3)
3203         glActiveTexture(GL_TEXTURE0 + Stage);
3204         vcheckGLcall("glActiveTexture");
3205 #else
3206         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3207         vcheckGLcall("glActiveTextureARB");
3208 #endif
3209     } else if (Stage > 0) {
3210         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3211     }
3212
3213     switch (Type) {
3214
3215     case D3DTSS_MINFILTER             :
3216     case D3DTSS_MIPFILTER             :
3217         {
3218             DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3219             DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3220             GLint realVal = GL_LINEAR;
3221
3222             if (ValueMIN == D3DTEXF_POINT) {
3223                 /* GL_NEAREST_* */
3224                 if (ValueMIP == D3DTEXF_POINT) {
3225                     realVal = GL_NEAREST_MIPMAP_NEAREST;
3226                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3227                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3228                 } else if (ValueMIP == D3DTEXF_NONE) {
3229                     realVal = GL_NEAREST;
3230                 } else {
3231                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3232                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3233                 }
3234             } else if (ValueMIN == D3DTEXF_LINEAR) {
3235                 /* GL_LINEAR_* */
3236                 if (ValueMIP == D3DTEXF_POINT) {
3237                     realVal = GL_LINEAR_MIPMAP_NEAREST;
3238                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3239                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3240                 } else if (ValueMIP == D3DTEXF_NONE) {
3241                     realVal = GL_LINEAR;
3242                 } else {
3243                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3244                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3245                 }
3246             } else if (ValueMIN == D3DTEXF_NONE) {
3247                 /* Doesn't really make sense - Windows just seems to disable
3248                    mipmapping when this occurs                              */
3249                 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3250                 realVal = GL_LINEAR;
3251
3252             } else {
3253                 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3254                 realVal = GL_LINEAR_MIPMAP_LINEAR;
3255             }
3256
3257             TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3258             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3259             checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3260         }
3261         break;
3262
3263     case D3DTSS_MAXANISOTROPY         :
3264       { 
3265         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3266           glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3267           checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3268         }
3269       }
3270       break;
3271
3272     case D3DTSS_MAGFILTER             :
3273         if (Value == D3DTEXF_POINT) {
3274             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3275             checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3276         } else if (Value == D3DTEXF_LINEAR) {
3277             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3278             checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3279         } else {
3280             FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3281         }
3282         break;
3283
3284     case D3DTSS_ALPHAOP               :
3285     case D3DTSS_COLOROP               :
3286         {
3287
3288             if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3289                 /* TODO: Disable by making this and all later levels disabled */
3290                 glDisable(GL_TEXTURE_1D);
3291                 checkGLcall("Disable GL_TEXTURE_1D");
3292                 glDisable(GL_TEXTURE_2D);
3293                 checkGLcall("Disable GL_TEXTURE_2D");
3294                 glDisable(GL_TEXTURE_3D);
3295                 checkGLcall("Disable GL_TEXTURE_3D");
3296                 break; /* Don't bother setting the texture operations */
3297             } else {
3298                 /* Enable only the appropriate texture dimension */
3299                 if (Type == D3DTSS_COLOROP) {
3300                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3301                         glEnable(GL_TEXTURE_1D);
3302                         checkGLcall("Enable GL_TEXTURE_1D");
3303                     } else {
3304                         glDisable(GL_TEXTURE_1D);
3305                         checkGLcall("Disable GL_TEXTURE_1D");
3306                     } 
3307                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3308                         glEnable(GL_TEXTURE_2D);
3309                         checkGLcall("Enable GL_TEXTURE_2D");
3310                     } else {
3311                         glDisable(GL_TEXTURE_2D);
3312                         checkGLcall("Disable GL_TEXTURE_2D");
3313                     }
3314                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3315                         glEnable(GL_TEXTURE_3D);
3316                         checkGLcall("Enable GL_TEXTURE_3D");
3317                     } else {
3318                         glDisable(GL_TEXTURE_3D);
3319                         checkGLcall("Disable GL_TEXTURE_3D");
3320                     }
3321                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3322                         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3323                         checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3324                     } else {
3325                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3326                         checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3327                     }
3328                 }
3329             }
3330             /* Drop through... (Except disable case) */
3331         case D3DTSS_COLORARG0             :
3332         case D3DTSS_COLORARG1             :
3333         case D3DTSS_COLORARG2             :
3334         case D3DTSS_ALPHAARG0             :
3335         case D3DTSS_ALPHAARG1             :
3336         case D3DTSS_ALPHAARG2             :
3337             {
3338                 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 || 
3339                                    Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3340                 if (isAlphaArg) {
3341                     set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3342                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1], 
3343                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2], 
3344                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3345                 } else {
3346                     set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3347                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1], 
3348                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2], 
3349                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3350                 }
3351             }
3352             break;
3353         }
3354
3355     case D3DTSS_ADDRESSU              :
3356     case D3DTSS_ADDRESSV              :
3357     case D3DTSS_ADDRESSW              :
3358         {
3359             GLint wrapParm = GL_REPEAT;
3360             switch (Value) {
3361             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
3362             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;      
3363             case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break;      /* FIXME: Not right, but better */
3364 #if defined(GL_VERSION_1_4)
3365             case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3366 #elif defined(GL_ARB_texture_mirrored_repeat)
3367             case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3368 #else
3369             case D3DTADDRESS_MIRROR:      /* Unsupported in OpenGL pre-1.4 */
3370 #endif
3371             case D3DTADDRESS_MIRRORONCE:  /* Unsupported in OpenGL         */
3372             default:
3373                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3374                 wrapParm = GL_REPEAT; 
3375             }
3376
3377             switch (Type) {
3378             case D3DTSS_ADDRESSU:
3379                 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3380                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3381                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3382                 break;
3383             case D3DTSS_ADDRESSV:
3384                 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3385                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3386                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3387                 break;
3388             case D3DTSS_ADDRESSW:
3389                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3390                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3391                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3392                 break;
3393             default: /* nop */
3394                 break; /** stupic compilator */
3395             }
3396         }
3397         break;
3398
3399     case D3DTSS_BORDERCOLOR           :
3400         {
3401             float col[4];
3402             D3DCOLORTOGLFLOAT4(Value, col);
3403             TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value); 
3404             glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3405             checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3406         }
3407         break;
3408
3409     case D3DTSS_TEXCOORDINDEX         :
3410         {
3411             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3412
3413             /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include 
3414                   one flag, you can still specify an index value, which the system uses to 
3415                   determine the texture wrapping mode.  
3416                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3417                   means use the vertex position (camera-space) as the input texture coordinates 
3418                   for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render 
3419                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3420                   to the TEXCOORDINDEX value */
3421           
3422             /** 
3423              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos 
3424              */
3425             switch (Value & 0xFFFF0000) {
3426             case D3DTSS_TCI_PASSTHRU:
3427               /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3428               glDisable(GL_TEXTURE_GEN_S);
3429               glDisable(GL_TEXTURE_GEN_T);
3430               glDisable(GL_TEXTURE_GEN_R);
3431               checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3432               break;
3433
3434             case D3DTSS_TCI_CAMERASPACEPOSITION:
3435               /* CameraSpacePosition means use the vertex position, transformed to camera space, 
3436                  as the input texture coordinates for this stage's texture transformation. This 
3437                  equates roughly to EYE_LINEAR                                                  */
3438               {
3439                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3440                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3441                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3442                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3443                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3444
3445                 glMatrixMode(GL_MODELVIEW);
3446                 glPushMatrix();
3447                 glLoadIdentity();
3448                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3449                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3450                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3451                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3452                 glPopMatrix();
3453                 
3454                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3455                 glEnable(GL_TEXTURE_GEN_S);
3456                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3457                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3458                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3459                 glEnable(GL_TEXTURE_GEN_T);
3460                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3461                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3462                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3463                 glEnable(GL_TEXTURE_GEN_R);
3464                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3465                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3466                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3467               }
3468               break;
3469
3470 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3471             case D3DTSS_TCI_CAMERASPACENORMAL:
3472               {
3473                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3474                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3475                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3476                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3477                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3478
3479                 glMatrixMode(GL_MODELVIEW);
3480                 glPushMatrix();
3481                 glLoadIdentity();
3482                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3483                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3484                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3485                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3486                 glPopMatrix();
3487
3488                 glEnable(GL_TEXTURE_GEN_S);
3489                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3490                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3491                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3492                 glEnable(GL_TEXTURE_GEN_T);
3493                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3494                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3495                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3496                 glEnable(GL_TEXTURE_GEN_R);
3497                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3498                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3499                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3500               }
3501               break;
3502 #endif
3503
3504 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3505             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3506               {
3507
3508                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3509                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3510                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3511                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3512                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3513
3514                 glMatrixMode(GL_MODELVIEW);
3515                 glPushMatrix();
3516                 glLoadIdentity();
3517                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3518                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3519                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3520                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3521                 glPopMatrix();
3522                 
3523                 glEnable(GL_TEXTURE_GEN_S);
3524                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3525                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3526                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3527                 glEnable(GL_TEXTURE_GEN_T);
3528                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3529                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3530                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3531                 glEnable(GL_TEXTURE_GEN_R);
3532                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3533                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3534                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3535               }
3536               break;
3537 #endif
3538
3539             /* Unhandled types: */
3540             default:
3541                 /* Todo: */
3542                 /* ? disable GL_TEXTURE_GEN_n ? */ 
3543                 glDisable(GL_TEXTURE_GEN_S);
3544                 glDisable(GL_TEXTURE_GEN_T);
3545                 glDisable(GL_TEXTURE_GEN_R);
3546                 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3547                 break;
3548             }
3549         }
3550         break;
3551
3552         /* Unhandled */
3553     case D3DTSS_BUMPENVMAT00          :
3554     case D3DTSS_BUMPENVMAT01          :
3555         TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3556         break;
3557     case D3DTSS_BUMPENVMAT10          :
3558     case D3DTSS_BUMPENVMAT11          :
3559         TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3560         break;
3561
3562     case D3DTSS_TEXTURETRANSFORMFLAGS :
3563         set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3564         break; 
3565
3566     case D3DTSS_MIPMAPLODBIAS         :
3567     case D3DTSS_MAXMIPLEVEL           :
3568     case D3DTSS_BUMPENVLSCALE         :
3569     case D3DTSS_BUMPENVLOFFSET        :
3570     case D3DTSS_RESULTARG             :
3571     default:
3572         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3573         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3574     }
3575
3576     LEAVE_GL();
3577
3578     return D3D_OK;
3579 }
3580 HRESULT  WINAPI  IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3581     ICOM_THIS(IDirect3DDevice8Impl,iface);
3582     TRACE("(%p) : stub\n", This);    /* FIXME: Needs doing, but called often and is harmless */
3583     return D3D_OK;
3584 }
3585 HRESULT  WINAPI  IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3586     ICOM_THIS(IDirect3DDevice8Impl,iface);
3587     FIXME("(%p) : stub\n", This);    
3588     return D3D_OK;
3589 }
3590 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3591     ICOM_THIS(IDirect3DDevice8Impl,iface);
3592     FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3593           pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3594     if (PaletteNumber >= MAX_PALETTES) {
3595         return D3DERR_INVALIDCALL;
3596     }
3597     memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3598     return D3D_OK;
3599 }
3600 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3601     ICOM_THIS(IDirect3DDevice8Impl,iface);
3602     if (PaletteNumber >= MAX_PALETTES) {
3603         return D3DERR_INVALIDCALL;
3604     }
3605     memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3606     FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3607           pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3608     return D3D_OK;
3609 }
3610 HRESULT  WINAPI  IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3611     ICOM_THIS(IDirect3DDevice8Impl,iface);
3612     FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3613     if (PaletteNumber >= MAX_PALETTES) {
3614         return D3DERR_INVALIDCALL;
3615     }
3616     This->currentPalette = PaletteNumber;
3617
3618 #if defined(GL_EXT_paletted_texture)
3619     if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3620
3621       ENTER_GL();
3622
3623       GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D,    /* target */
3624                                   GL_RGBA,          /* internal format */
3625                                   256,              /* table size */
3626                                   GL_RGBA,          /* table format */
3627                                   GL_UNSIGNED_BYTE, /* table type */
3628                                   This->palettes[PaletteNumber]);
3629       checkGLcall("glColorTableEXT");
3630
3631       LEAVE_GL();
3632
3633     } else {
3634       /* Delayed palette handling ... waiting for software emulation into preload code */
3635     }
3636 #endif
3637     return D3D_OK;
3638 }
3639 HRESULT  WINAPI  IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3640     ICOM_THIS(IDirect3DDevice8Impl,iface);
3641     *PaletteNumber = This->currentPalette;
3642     FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3643     return D3D_OK;
3644 }
3645 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3646
3647     ICOM_THIS(IDirect3DDevice8Impl,iface);
3648     This->StateBlock->streamIsUP = FALSE;
3649
3650     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3651     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3652
3653     return D3D_OK;
3654 }
3655 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3656                                                            UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3657     UINT idxStride = 2;
3658     IDirect3DIndexBuffer8      *pIB;
3659     D3DINDEXBUFFER_DESC         IdxBufDsc;
3660
3661     ICOM_THIS(IDirect3DDevice8Impl,iface);
3662     pIB = This->StateBlock->pIndexData;
3663     This->StateBlock->streamIsUP = FALSE;
3664
3665     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, 
3666           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3667           minIndex, NumVertices, startIndex, primCount);
3668
3669     IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3670     if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3671         idxStride = 2;
3672     } else {
3673         idxStride = 4;
3674     }
3675
3676     drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3677                    minIndex);
3678
3679     return D3D_OK;
3680 }
3681 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3682     ICOM_THIS(IDirect3DDevice8Impl,iface);
3683
3684     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), 
3685           PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3686
3687     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3688
3689     /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3690     This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData; 
3691     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3692     This->StateBlock->streamIsUP = TRUE;
3693     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3694     This->StateBlock->stream_stride[0] = 0;
3695     This->StateBlock->stream_source[0] = NULL;
3696
3697     /*stream zero settings set to null at end */
3698     return D3D_OK;
3699 }
3700 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3701                                                              UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3702                                                              D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3703                                                              UINT VertexStreamZeroStride) {
3704     int idxStride;
3705     ICOM_THIS(IDirect3DDevice8Impl,iface);
3706     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3707           MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,  IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3708
3709     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3710     if (IndexDataFormat == D3DFMT_INDEX16) {
3711         idxStride = 2;
3712     } else {
3713         idxStride = 4;
3714     }
3715
3716     /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3717     This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3718     This->StateBlock->streamIsUP = TRUE;
3719     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3720     drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3721
3722     /*stream zero settings set to null at end */
3723     This->StateBlock->stream_source[0] = NULL;
3724     This->StateBlock->stream_stride[0] = 0;
3725     IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3726
3727     return D3D_OK;
3728 }
3729 HRESULT  WINAPI  IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3730     ICOM_THIS(IDirect3DDevice8Impl,iface);
3731     FIXME("(%p) : stub\n", This);    return D3D_OK;
3732 }
3733 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3734     ICOM_THIS(IDirect3DDevice8Impl,iface);
3735     IDirect3DVertexShaderImpl* object;
3736     IDirect3DVertexShaderDeclarationImpl* attached_decl;
3737     HRESULT res;
3738     UINT i;
3739
3740     TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3741     if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3742       return D3DERR_INVALIDCALL;
3743     }
3744     for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3745     if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3746       return D3DERR_OUTOFVIDEOMEMORY;
3747     }
3748
3749     /** Create the Vertex Shader */
3750     res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3751     /** TODO: check FAILED(res) */
3752
3753     /** Create and Bind the Vertex Shader Declaration */
3754     res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3755     /** TODO: check FAILED(res) */
3756
3757     VertexShaders[i] = object;
3758     VertexShaderDeclarations[i] = attached_decl;
3759     *pHandle = VS_HIGHESTFIXEDFXF + i;
3760     TRACE("Finished creating vertex shader %lx\n", *pHandle);
3761
3762     return D3D_OK;
3763 }
3764 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3765     ICOM_THIS(IDirect3DDevice8Impl,iface);
3766
3767     This->UpdateStateBlock->VertexShader = Handle;
3768     This->UpdateStateBlock->Changed.vertexShader = TRUE;
3769     This->UpdateStateBlock->Set.vertexShader = TRUE;
3770     
3771     if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3772       TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3773       This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3774       This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3775       This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3776     } else { /* use a fvf, so desactivate the vshader decl */
3777       TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3778       This->UpdateStateBlock->vertexShaderDecl = NULL;
3779       This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3780       This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3781     }
3782     /* Handle recording of state blocks */
3783     if (This->isRecordingState) {
3784       TRACE("Recording... not performing anything\n");
3785       return D3D_OK;
3786     }
3787     /**
3788      * TODO: merge HAL shaders context switching from prototype
3789      */
3790     return D3D_OK;
3791 }
3792 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3793     ICOM_THIS(IDirect3DDevice8Impl,iface);
3794     TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3795     *pHandle = This->StateBlock->VertexShader;
3796     return D3D_OK;
3797 }
3798
3799 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3800     ICOM_THIS(IDirect3DDevice8Impl,iface);
3801     IDirect3DVertexShaderImpl* object; 
3802     IDirect3DVertexShaderDeclarationImpl* attached_decl;
3803
3804     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3805       return D3DERR_INVALIDCALL;
3806     }
3807
3808     /**
3809      * Delete Vertex Shader
3810      */
3811     object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3812     if (NULL == object) {
3813       return D3DERR_INVALIDCALL;
3814     }
3815     TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3816     /* TODO: check validity of object */
3817     if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3818     HeapFree(GetProcessHeap(), 0, (void *)object->data);
3819     HeapFree(GetProcessHeap(), 0, (void *)object);
3820     VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3821
3822     /**
3823      * Delete Vertex Shader Declaration
3824      */
3825     attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3826     if (NULL == attached_decl) {
3827       return D3DERR_INVALIDCALL;
3828     } 
3829     TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3830     /* TODO: check validity of object */
3831     HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3832     HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3833     VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3834
3835     return D3D_OK;
3836 }
3837
3838 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3839   ICOM_THIS(IDirect3DDevice8Impl,iface);
3840
3841   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3842     ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3843     return D3DERR_INVALIDCALL;
3844   }
3845   if (NULL == pConstantData) {
3846     return D3DERR_INVALIDCALL;
3847   }
3848   if (ConstantCount > 1) {
3849     FLOAT* f = (FLOAT*)pConstantData;
3850     UINT i;
3851     TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3852     for (i = 0; i < ConstantCount; ++i) {
3853       TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3854       f += 4;
3855     }
3856   } else { 
3857     FLOAT* f = (FLOAT*) pConstantData;
3858     TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3859   }
3860   This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3861   memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3862   return D3D_OK;
3863 }
3864 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3865   ICOM_THIS(IDirect3DDevice8Impl,iface);
3866
3867   TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3868   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3869     return D3DERR_INVALIDCALL;
3870   }
3871   if (NULL == pConstantData) {
3872     return D3DERR_INVALIDCALL;
3873   }
3874   memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3875   return D3D_OK;
3876 }
3877 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3878   /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3879   IDirect3DVertexShaderDeclarationImpl* attached_decl;
3880   
3881   attached_decl = VERTEX_SHADER_DECL(Handle);
3882   if (NULL == attached_decl) {
3883     return D3DERR_INVALIDCALL;
3884   }
3885   return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3886 }
3887 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3888   /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3889   IDirect3DVertexShaderImpl* object;
3890   
3891   object = VERTEX_SHADER(Handle);
3892   if (NULL == object) {
3893     return D3DERR_INVALIDCALL;
3894   }
3895   return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3896 }
3897
3898 HRESULT  WINAPI  IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3899     ICOM_THIS(IDirect3DDevice8Impl,iface);
3900     IDirect3DIndexBuffer8 *oldIdxs;
3901
3902     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3903     oldIdxs = This->StateBlock->pIndexData;
3904
3905     This->UpdateStateBlock->Changed.Indices = TRUE;
3906     This->UpdateStateBlock->Set.Indices = TRUE;
3907     This->UpdateStateBlock->pIndexData = pIndexData;
3908     This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3909
3910     /* Handle recording of state blocks */
3911     if (This->isRecordingState) {
3912         TRACE("Recording... not performing anything\n");
3913         return D3D_OK;
3914     }
3915
3916     if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3917     if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3918     return D3D_OK;
3919 }
3920 HRESULT  WINAPI  IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3921     ICOM_THIS(IDirect3DDevice8Impl,iface);
3922     FIXME("(%p) : stub\n", This);
3923
3924     *ppIndexData = This->StateBlock->pIndexData;
3925     /* up ref count on ppindexdata */
3926     if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3927     *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3928
3929     return D3D_OK;
3930 }
3931 HRESULT  WINAPI  IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3932     ICOM_THIS(IDirect3DDevice8Impl,iface);
3933     IDirect3DPixelShaderImpl* object;
3934     HRESULT res;
3935     UINT i;
3936
3937     TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3938     if (NULL == pFunction || NULL == pHandle) {
3939       return D3DERR_INVALIDCALL;
3940     }
3941     for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3942     if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3943       return D3DERR_OUTOFVIDEOMEMORY;
3944     }
3945
3946     /** Create the Pixel Shader */
3947     res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3948     if (SUCCEEDED(res)) {
3949       PixelShaders[i] = object;
3950       *pHandle = VS_HIGHESTFIXEDFXF + i;
3951       return D3D_OK;
3952     } 
3953     *pHandle = 0xFFFFFFFF;
3954     return res;
3955 }
3956 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3957     ICOM_THIS(IDirect3DDevice8Impl,iface);
3958
3959     This->UpdateStateBlock->PixelShader = Handle;
3960     This->UpdateStateBlock->Changed.pixelShader = TRUE;
3961     This->UpdateStateBlock->Set.pixelShader = TRUE;
3962
3963     /* Handle recording of state blocks */
3964     if (This->isRecordingState) {
3965         TRACE_(d3d_shader)("Recording... not performing anything\n");
3966         return D3D_OK;
3967     }
3968
3969     /* FIXME: Quieten when not being used */
3970     if (Handle != 0) {
3971       FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3972     } else {
3973       TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3974     }
3975
3976     return D3D_OK;
3977 }
3978 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3979     ICOM_THIS(IDirect3DDevice8Impl,iface);
3980     TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3981     *pHandle = This->StateBlock->PixelShader;
3982     return D3D_OK;
3983 }
3984
3985 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3986     ICOM_THIS(IDirect3DDevice8Impl,iface);
3987     IDirect3DPixelShaderImpl* object;   
3988
3989     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3990       return D3DERR_INVALIDCALL;
3991     }
3992     object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3993     TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3994     /* TODO: check validity of object before free */
3995     if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3996     HeapFree(GetProcessHeap(), 0, (void *)object->data);
3997     HeapFree(GetProcessHeap(), 0, (void *)object);
3998     PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3999
4000     return D3D_OK;
4001 }
4002
4003 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4004   ICOM_THIS(IDirect3DDevice8Impl,iface);
4005
4006   if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4007     ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4008     return D3DERR_INVALIDCALL;
4009   }
4010   if (NULL == pConstantData) {
4011     return D3DERR_INVALIDCALL;
4012   }
4013   if (ConstantCount > 1) {
4014     FLOAT* f = (FLOAT*)pConstantData;
4015     UINT i;
4016     TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4017     for (i = 0; i < ConstantCount; ++i) {
4018       TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4019       f += 4;
4020     }
4021   } else { 
4022     FLOAT* f = (FLOAT*) pConstantData;
4023     TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4024   }
4025   This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4026   memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4027   return D3D_OK;
4028 }
4029 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4030   ICOM_THIS(IDirect3DDevice8Impl,iface);
4031
4032   TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4033   if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4034     return D3DERR_INVALIDCALL;
4035   }
4036   if (NULL == pConstantData) {
4037     return D3DERR_INVALIDCALL;
4038   }
4039   memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4040   return D3D_OK;
4041 }
4042 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4043     IDirect3DPixelShaderImpl* object;
4044
4045     object = PIXEL_SHADER(Handle);
4046     if (NULL == object) {
4047       return D3DERR_INVALIDCALL;
4048     } 
4049     return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4050 }
4051 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4052     ICOM_THIS(IDirect3DDevice8Impl,iface);
4053     FIXME("(%p) : stub\n", This);    return D3D_OK;
4054 }
4055 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4056     ICOM_THIS(IDirect3DDevice8Impl,iface);
4057     FIXME("(%p) : stub\n", This);    return D3D_OK;
4058 }
4059 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4060     ICOM_THIS(IDirect3DDevice8Impl,iface);
4061     FIXME("(%p) : stub\n", This);    return D3D_OK;
4062 }
4063
4064 HRESULT  WINAPI  IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4065     IDirect3DVertexBuffer8 *oldSrc;
4066     ICOM_THIS(IDirect3DDevice8Impl,iface);
4067
4068     oldSrc = This->StateBlock->stream_source[StreamNumber];
4069     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4070
4071     This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4072     This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4073     This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4074     This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4075
4076     /* Handle recording of state blocks */
4077     if (This->isRecordingState) {
4078         TRACE("Recording... not performing anything\n");
4079         return D3D_OK;
4080     }
4081
4082     if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4083     if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4084     return D3D_OK;
4085 }
4086 HRESULT  WINAPI  IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4087     ICOM_THIS(IDirect3DDevice8Impl,iface);
4088     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4089     *pStream = This->StateBlock->stream_source[StreamNumber];
4090     *pStride = This->StateBlock->stream_stride[StreamNumber];
4091     IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4092     return D3D_OK;
4093 }
4094
4095
4096 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4097 {
4098     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4099     IDirect3DDevice8Impl_QueryInterface,
4100     IDirect3DDevice8Impl_AddRef,
4101     IDirect3DDevice8Impl_Release,
4102     IDirect3DDevice8Impl_TestCooperativeLevel,
4103     IDirect3DDevice8Impl_GetAvailableTextureMem,
4104     IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4105     IDirect3DDevice8Impl_GetDirect3D,
4106     IDirect3DDevice8Impl_GetDeviceCaps,
4107     IDirect3DDevice8Impl_GetDisplayMode,
4108     IDirect3DDevice8Impl_GetCreationParameters,
4109     IDirect3DDevice8Impl_SetCursorProperties,
4110     IDirect3DDevice8Impl_SetCursorPosition,
4111     IDirect3DDevice8Impl_ShowCursor,
4112     IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4113     IDirect3DDevice8Impl_Reset,
4114     IDirect3DDevice8Impl_Present,
4115     IDirect3DDevice8Impl_GetBackBuffer,
4116     IDirect3DDevice8Impl_GetRasterStatus,
4117     IDirect3DDevice8Impl_SetGammaRamp,
4118     IDirect3DDevice8Impl_GetGammaRamp,
4119     IDirect3DDevice8Impl_CreateTexture,
4120     IDirect3DDevice8Impl_CreateVolumeTexture,
4121     IDirect3DDevice8Impl_CreateCubeTexture,
4122     IDirect3DDevice8Impl_CreateVertexBuffer,
4123     IDirect3DDevice8Impl_CreateIndexBuffer,
4124     IDirect3DDevice8Impl_CreateRenderTarget,
4125     IDirect3DDevice8Impl_CreateDepthStencilSurface,
4126     IDirect3DDevice8Impl_CreateImageSurface,
4127     IDirect3DDevice8Impl_CopyRects,
4128     IDirect3DDevice8Impl_UpdateTexture,
4129     IDirect3DDevice8Impl_GetFrontBuffer,
4130     IDirect3DDevice8Impl_SetRenderTarget,
4131     IDirect3DDevice8Impl_GetRenderTarget,
4132     IDirect3DDevice8Impl_GetDepthStencilSurface,
4133     IDirect3DDevice8Impl_BeginScene,
4134     IDirect3DDevice8Impl_EndScene,
4135     IDirect3DDevice8Impl_Clear,
4136     IDirect3DDevice8Impl_SetTransform,
4137     IDirect3DDevice8Impl_GetTransform,
4138     IDirect3DDevice8Impl_MultiplyTransform,
4139     IDirect3DDevice8Impl_SetViewport,
4140     IDirect3DDevice8Impl_GetViewport,
4141     IDirect3DDevice8Impl_SetMaterial,
4142     IDirect3DDevice8Impl_GetMaterial,
4143     IDirect3DDevice8Impl_SetLight,
4144     IDirect3DDevice8Impl_GetLight,
4145     IDirect3DDevice8Impl_LightEnable,
4146     IDirect3DDevice8Impl_GetLightEnable,
4147     IDirect3DDevice8Impl_SetClipPlane,
4148     IDirect3DDevice8Impl_GetClipPlane,
4149     IDirect3DDevice8Impl_SetRenderState,
4150     IDirect3DDevice8Impl_GetRenderState,
4151     IDirect3DDevice8Impl_BeginStateBlock,
4152     IDirect3DDevice8Impl_EndStateBlock,
4153     IDirect3DDevice8Impl_ApplyStateBlock,
4154     IDirect3DDevice8Impl_CaptureStateBlock,
4155     IDirect3DDevice8Impl_DeleteStateBlock,
4156     IDirect3DDevice8Impl_CreateStateBlock,
4157     IDirect3DDevice8Impl_SetClipStatus,
4158     IDirect3DDevice8Impl_GetClipStatus,
4159     IDirect3DDevice8Impl_GetTexture,
4160     IDirect3DDevice8Impl_SetTexture,
4161     IDirect3DDevice8Impl_GetTextureStageState,
4162     IDirect3DDevice8Impl_SetTextureStageState,
4163     IDirect3DDevice8Impl_ValidateDevice,
4164     IDirect3DDevice8Impl_GetInfo,
4165     IDirect3DDevice8Impl_SetPaletteEntries,
4166     IDirect3DDevice8Impl_GetPaletteEntries,
4167     IDirect3DDevice8Impl_SetCurrentTexturePalette,
4168     IDirect3DDevice8Impl_GetCurrentTexturePalette,
4169     IDirect3DDevice8Impl_DrawPrimitive,
4170     IDirect3DDevice8Impl_DrawIndexedPrimitive,
4171     IDirect3DDevice8Impl_DrawPrimitiveUP,
4172     IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4173     IDirect3DDevice8Impl_ProcessVertices,
4174     IDirect3DDevice8Impl_CreateVertexShader,
4175     IDirect3DDevice8Impl_SetVertexShader,
4176     IDirect3DDevice8Impl_GetVertexShader,
4177     IDirect3DDevice8Impl_DeleteVertexShader,
4178     IDirect3DDevice8Impl_SetVertexShaderConstant,
4179     IDirect3DDevice8Impl_GetVertexShaderConstant,
4180     IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4181     IDirect3DDevice8Impl_GetVertexShaderFunction,
4182     IDirect3DDevice8Impl_SetStreamSource,
4183     IDirect3DDevice8Impl_GetStreamSource,
4184     IDirect3DDevice8Impl_SetIndices,
4185     IDirect3DDevice8Impl_GetIndices,
4186     IDirect3DDevice8Impl_CreatePixelShader,
4187     IDirect3DDevice8Impl_SetPixelShader,
4188     IDirect3DDevice8Impl_GetPixelShader,
4189     IDirect3DDevice8Impl_DeletePixelShader,
4190     IDirect3DDevice8Impl_SetPixelShaderConstant,
4191     IDirect3DDevice8Impl_GetPixelShaderConstant,
4192     IDirect3DDevice8Impl_GetPixelShaderFunction,
4193     IDirect3DDevice8Impl_DrawRectPatch,
4194     IDirect3DDevice8Impl_DrawTriPatch,
4195     IDirect3DDevice8Impl_DeletePatch
4196 };
4197
4198 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4199 {
4200 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4201   ICOM_THIS(IDirect3DDevice8Impl,iface);
4202
4203   ENTER_GL();
4204
4205 #if 0
4206   if (This->glCtx != This->render_ctx) {
4207     glXDestroyContext(This->display, This->render_ctx);
4208     This->render_ctx = This->glCtx;
4209   }
4210 #endif
4211   if (This->win != This->drawable) {
4212     glXDestroyPbuffer(This->display, This->drawable);
4213     This->drawable = This->win;
4214   }
4215
4216   LEAVE_GL();
4217
4218 #endif
4219   return D3D_OK;
4220 }
4221
4222 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4223                                                 IDirect3DSurface8* RenderSurface, 
4224                                                 IDirect3DSurface8* StencilSurface) {
4225
4226   HRESULT ret =  D3DERR_INVALIDCALL; 
4227   /**
4228    * Currently only active for GLX >= 1.3
4229    * for others versions we'll have to use GLXPixmaps
4230    *
4231    * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4232    * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4233    * so only check OpenGL version
4234    */
4235 #if defined(GL_VERSION_1_3) 
4236   GLXFBConfig* cfgs = NULL;
4237   int nCfgs = 0;
4238   int attribs[256];
4239   int nAttribs = 0;
4240   D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4241   D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4242   UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4243   UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4244   IDirect3DSurface8Impl* tmp;
4245
4246   ICOM_THIS(IDirect3DDevice8Impl,iface);
4247  
4248 #define PUSH1(att)        attribs[nAttribs++] = (att); 
4249 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4250
4251   PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4252   PUSH2(GLX_X_RENDERABLE,  TRUE);
4253   PUSH2(GLX_DOUBLEBUFFER, TRUE);
4254   
4255   switch (BackBufferFormat) {
4256     /* color buffer */
4257   case D3DFMT_P8:
4258     PUSH2(GLX_RENDER_TYPE,  GLX_COLOR_INDEX_BIT);
4259     PUSH2(GLX_BUFFER_SIZE,  8);
4260     PUSH2(GLX_DOUBLEBUFFER, TRUE);
4261     break;
4262     
4263   case D3DFMT_R3G3B2:
4264     PUSH2(GLX_RENDER_TYPE,  GLX_RGBA_BIT);
4265     PUSH2(GLX_RED_SIZE,     3);
4266     PUSH2(GLX_GREEN_SIZE,   3);
4267     PUSH2(GLX_BLUE_SIZE,    2);
4268     break;
4269     
4270   case D3DFMT_A1R5G5B5:
4271     PUSH2(GLX_ALPHA_SIZE,   1);
4272   case D3DFMT_X1R5G5B5:
4273     PUSH2(GLX_RED_SIZE,     5);
4274     PUSH2(GLX_GREEN_SIZE,   5);
4275     PUSH2(GLX_BLUE_SIZE,    5);
4276     break;
4277     
4278   case D3DFMT_R5G6B5:
4279     PUSH2(GLX_RED_SIZE,     5);
4280     PUSH2(GLX_GREEN_SIZE,   6);
4281     PUSH2(GLX_BLUE_SIZE,    5);
4282     break;
4283     
4284   case D3DFMT_A4R4G4B4:
4285     PUSH2(GLX_ALPHA_SIZE,   4);
4286   case D3DFMT_X4R4G4B4:
4287     PUSH2(GLX_RED_SIZE,     4);
4288     PUSH2(GLX_GREEN_SIZE,   4);
4289     PUSH2(GLX_BLUE_SIZE,    4);
4290     break;
4291     
4292   case D3DFMT_A8R8G8B8:
4293     PUSH2(GLX_ALPHA_SIZE,   8);
4294   case D3DFMT_R8G8B8:
4295   case D3DFMT_X8R8G8B8:
4296     PUSH2(GLX_RED_SIZE,     8);
4297     PUSH2(GLX_GREEN_SIZE,   8);
4298     PUSH2(GLX_BLUE_SIZE,    8);
4299     break;
4300
4301   default:
4302     break;
4303   }
4304    
4305   switch (StencilBufferFormat) { 
4306   case D3DFMT_D16_LOCKABLE:
4307   case D3DFMT_D16:
4308     PUSH2(GLX_DEPTH_SIZE,   16);
4309     break;
4310     
4311   case D3DFMT_D15S1:
4312     PUSH2(GLX_DEPTH_SIZE,   15);
4313     break;
4314     
4315   case D3DFMT_D24X8:
4316     PUSH2(GLX_DEPTH_SIZE,   24);
4317     break;
4318     
4319   case D3DFMT_D24X4S4:
4320     PUSH2(GLX_DEPTH_SIZE,   24);
4321     PUSH2(GLX_STENCIL_SIZE, 4);
4322     break;
4323     
4324   case D3DFMT_D24S8:
4325     PUSH2(GLX_DEPTH_SIZE,   24);
4326     PUSH2(GLX_STENCIL_SIZE, 8);
4327     break;
4328     
4329   case D3DFMT_D32:
4330     PUSH2(GLX_DEPTH_SIZE,   32);
4331     break;
4332
4333   default:
4334     break;
4335   }
4336
4337   PUSH1(None);
4338   
4339   ENTER_GL();
4340
4341   cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4342   if (NULL != cfgs) {
4343 #if 0
4344     int i;
4345     for (i = 0; i < nCfgs; ++i) {
4346       TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4347     }
4348 #endif
4349
4350     if (NULL != This->renderTarget) {
4351       GLenum prev_read;      
4352       glFlush();
4353       vcheckGLcall("glFlush");
4354
4355 #if 0
4356       /** very very usefull debug code */
4357       glXSwapBuffers(This->display, This->drawable);   
4358       printf("Hit Enter to get next frame ...\n");
4359       getchar();
4360 #endif
4361
4362       glGetIntegerv(GL_READ_BUFFER, &prev_read);
4363       vcheckGLcall("glIntegerv");
4364       glReadBuffer(GL_BACK);
4365       vcheckGLcall("glReadBuffer");
4366       {
4367         long j;
4368         long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4369
4370         if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4371             pitch = pitch / 2;
4372
4373         for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4374           glReadPixels(0, 
4375                        This->renderTarget->myDesc.Height - j - 1, 
4376                        This->renderTarget->myDesc.Width, 
4377                        1,
4378                        D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format), 
4379                        D3DFmt2GLType(This, This->renderTarget->myDesc.Format), 
4380                        This->renderTarget->allocatedMemory + j * pitch);
4381           vcheckGLcall("glReadPixels");
4382         }
4383       }      
4384       glReadBuffer(prev_read);
4385       vcheckGLcall("glReadBuffer");
4386     }
4387
4388     if (BackBufferFormat != This->renderTarget->myDesc.Format && 
4389         StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4390       nAttribs = 0;
4391       PUSH2(GLX_PBUFFER_WIDTH,  Width);
4392       PUSH2(GLX_PBUFFER_HEIGHT, Height);
4393       PUSH1(None);
4394       This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4395             
4396       This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4397       if (NULL == This->render_ctx) {
4398         ERR("cannot create glxContext\n"); 
4399       }
4400
4401       glFlush();
4402       glXSwapBuffers(This->display, This->drawable);
4403       if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4404         TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4405       }
4406       checkGLcall("glXMakeContextCurrent");
4407     }
4408
4409     tmp = This->renderTarget;
4410     This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4411     IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4412     IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4413
4414     tmp = This->stencilBufferTarget;
4415     This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4416     if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4417     if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4418
4419     ret = D3D_OK;
4420
4421   } else {
4422     ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4423   }
4424
4425 #undef PUSH1
4426 #undef PUSH2
4427
4428   LEAVE_GL();
4429
4430 #endif
4431
4432   return ret;
4433 }