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