Authors: Christian Costa <titan.costa@wanadoo.fr>, Jason Edmeades <us@the-edmeades...
[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, dont 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
2246         case D3DZB_USEW:
2247         default:
2248             FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2249         }
2250         break;
2251
2252     case D3DRS_CULLMODE                  :
2253
2254         /* If we are culling "back faces with clockwise vertices" then
2255            set front faces to be counter clockwise and enable culling  
2256            of back faces                                               */
2257         switch ((D3DCULL) Value) {
2258         case D3DCULL_NONE:
2259             glDisable(GL_CULL_FACE);
2260             checkGLcall("glDisable GL_CULL_FACE");
2261             break;
2262         case D3DCULL_CW:
2263             glEnable(GL_CULL_FACE);
2264             checkGLcall("glEnable GL_CULL_FACE");
2265             if (This->renderUpsideDown) {
2266                 glFrontFace(GL_CW);
2267                 checkGLcall("glFrontFace GL_CW");
2268             } else {
2269                 glFrontFace(GL_CCW);
2270                 checkGLcall("glFrontFace GL_CCW");
2271             }
2272             glCullFace(GL_BACK);
2273             break;
2274         case D3DCULL_CCW:
2275             glEnable(GL_CULL_FACE);
2276             checkGLcall("glEnable GL_CULL_FACE");
2277             if (This->renderUpsideDown) {
2278                 glFrontFace(GL_CCW); 
2279                 checkGLcall("glFrontFace GL_CCW");
2280             } else {
2281                 glFrontFace(GL_CW);
2282                 checkGLcall("glFrontFace GL_CW");
2283             }
2284             glCullFace(GL_BACK);
2285             break;
2286         default:
2287             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2288         }
2289         break;
2290
2291     case D3DRS_SHADEMODE                 :
2292         switch ((D3DSHADEMODE) Value) {
2293         case D3DSHADE_FLAT:
2294             glShadeModel(GL_FLAT);
2295             checkGLcall("glShadeModel");
2296             break;
2297         case D3DSHADE_GOURAUD:
2298             glShadeModel(GL_SMOOTH);
2299             checkGLcall("glShadeModel");
2300             break;
2301         case D3DSHADE_PHONG:
2302             FIXME("D3DSHADE_PHONG isn't supported?\n");
2303
2304             LEAVE_GL();
2305             return D3DERR_INVALIDCALL;
2306         default:
2307             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2308         }
2309         break;
2310
2311     case D3DRS_DITHERENABLE              :
2312         if (Value) {
2313             glEnable(GL_DITHER);
2314             checkGLcall("glEnable GL_DITHER");
2315         } else {
2316             glDisable(GL_DITHER);
2317             checkGLcall("glDisable GL_DITHER");
2318         }
2319         break;
2320
2321     case D3DRS_ZWRITEENABLE              :
2322         if (Value) {
2323             glDepthMask(1);
2324             checkGLcall("glDepthMask");
2325         } else {
2326             glDepthMask(0);
2327             checkGLcall("glDepthMask");
2328         }
2329         break;
2330
2331     case D3DRS_ZFUNC                     :
2332         {
2333             int glParm = GL_LESS;
2334
2335             switch ((D3DCMPFUNC) Value) {
2336             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2337             case D3DCMP_LESS:          glParm=GL_LESS; break;
2338             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2339             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2340             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2341             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2342             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2343             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2344             default:
2345                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2346             }
2347             glDepthFunc(glParm);
2348             checkGLcall("glDepthFunc");
2349         }
2350         break;
2351
2352     case D3DRS_AMBIENT                   :
2353         {
2354             float col[4];
2355             D3DCOLORTOGLFLOAT4(Value, col);
2356             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2357             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2358             checkGLcall("glLightModel for MODEL_AMBIENT");
2359
2360         }
2361         break;
2362
2363     case D3DRS_ALPHABLENDENABLE          :
2364         if (Value) {
2365             glEnable(GL_BLEND);
2366             checkGLcall("glEnable GL_BLEND");
2367         } else {
2368             glDisable(GL_BLEND);
2369             checkGLcall("glDisable GL_BLEND");
2370         };
2371         break;
2372
2373     case D3DRS_SRCBLEND                  :
2374     case D3DRS_DESTBLEND                 :
2375         {
2376             int newVal = GL_ZERO;
2377             switch (Value) {
2378             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
2379             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
2380             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
2381             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
2382             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
2383             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
2384             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
2385             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
2386             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
2387             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
2388             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
2389
2390             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
2391                 This->srcBlend = newVal;
2392                 This->dstBlend = newVal;
2393                 break;
2394
2395             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
2396                 This->srcBlend = newVal;
2397                 This->dstBlend = newVal;
2398                 break;
2399             default:
2400                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2401             }
2402
2403             if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2404             if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2405             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2406             glBlendFunc(This->srcBlend, This->dstBlend);
2407
2408             checkGLcall("glBlendFunc");
2409         }
2410         break;
2411
2412     case D3DRS_ALPHATESTENABLE           :
2413         if (Value) {
2414             glEnable(GL_ALPHA_TEST);
2415             checkGLcall("glEnable GL_ALPHA_TEST");
2416         } else {
2417             glDisable(GL_ALPHA_TEST);
2418             checkGLcall("glDisable GL_ALPHA_TEST");
2419         }
2420         break;
2421
2422     case D3DRS_ALPHAFUNC                 :
2423         {
2424             int glParm = GL_LESS;
2425             float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2426
2427             switch ((D3DCMPFUNC) Value) {
2428             case D3DCMP_NEVER:         glParm = GL_NEVER; break;
2429             case D3DCMP_LESS:          glParm = GL_LESS; break;
2430             case D3DCMP_EQUAL:         glParm = GL_EQUAL; break;
2431             case D3DCMP_LESSEQUAL:     glParm = GL_LEQUAL; break;
2432             case D3DCMP_GREATER:       glParm = GL_GREATER; break;
2433             case D3DCMP_NOTEQUAL:      glParm = GL_NOTEQUAL; break;
2434             case D3DCMP_GREATEREQUAL:  glParm = GL_GEQUAL; break;
2435             case D3DCMP_ALWAYS:        glParm = GL_ALWAYS; break;
2436             default:
2437                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2438             }
2439             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2440             glAlphaFunc(glParm, ref);
2441             This->alphafunc = glParm;
2442             checkGLcall("glAlphaFunc");
2443         }
2444         break;
2445
2446     case D3DRS_ALPHAREF                  :
2447         {
2448             int glParm = This->alphafunc;
2449             float ref = 1.0f;
2450
2451             ref = ((float) Value) / 255.0f;
2452             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2453             glAlphaFunc(glParm, ref);
2454             checkGLcall("glAlphaFunc");
2455         }
2456         break;
2457
2458     case D3DRS_CLIPPLANEENABLE           :
2459     case D3DRS_CLIPPING                  :
2460         {
2461             /* Ensure we only do the changed clip planes */
2462             DWORD enable  = 0xFFFFFFFF;
2463             DWORD disable = 0x00000000;
2464             
2465             /* If enabling / disabling all */
2466             if (State == D3DRS_CLIPPING) {
2467                 if (Value) {
2468                     enable  = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2469                     disable = 0x00;
2470                 } else {
2471                     disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2472                     enable  = 0x00;
2473                 }
2474             } else {
2475                 enable =   Value & ~OldValue;
2476                 disable = ~Value &  OldValue;
2477             }
2478             
2479             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
2480             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
2481             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
2482             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
2483             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
2484             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
2485             
2486             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2487             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2488             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2489             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2490             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2491             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2492         }
2493         break;
2494
2495     case D3DRS_BLENDOP                   :
2496         {
2497             int glParm = GL_FUNC_ADD;
2498
2499             switch ((D3DBLENDOP) Value) {
2500             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
2501             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
2502             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2503             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
2504             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
2505             default:
2506                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2507             }
2508             TRACE("glBlendEquation(%x)\n", glParm);
2509             glBlendEquation(glParm);
2510             checkGLcall("glBlendEquation");
2511         }
2512         break;
2513
2514     case D3DRS_TEXTUREFACTOR             :
2515         {
2516             int i;
2517
2518             /* Note the texture color applies to all textures whereas 
2519                GL_TEXTURE_ENV_COLOR applies to active only */
2520             float col[4];
2521             D3DCOLORTOGLFLOAT4(Value, col);
2522             /* Set the default alpha blend color */
2523             glBlendColor(col[0], col[1], col[2], col[3]);
2524             checkGLcall("glBlendColor");
2525
2526             /* And now the default texture color as well */
2527             for (i = 0; i < GL_LIMITS(textures); i++) {
2528
2529                 /* Note the D3DRS value applies to all textures, but GL has one
2530                    per texture, so apply it now ready to be used!               */
2531                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2532 #if defined(GL_VERSION_1_3)
2533                     glActiveTexture(GL_TEXTURE0 + i);
2534 #else
2535                     glActiveTextureARB(GL_TEXTURE0_ARB + i);
2536 #endif
2537                     checkGLcall("Activate texture.. to update const color");
2538                 } else if (i>0) {
2539                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2540                 }
2541
2542                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2543                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2544             }
2545         }
2546         break;
2547
2548     case D3DRS_SPECULARENABLE            : 
2549         {
2550             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2551                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2552                specular color. This is wrong:
2553                Separate specular color means the specular colour is maintained separately, whereas
2554                single color means it is merged in. However in both cases they are being used to
2555                some extent.
2556                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2557                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2558                   running 1.4 yet!
2559              */
2560               if (Value) {
2561                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2562                 checkGLcall("glMaterialfv");
2563                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2564                   glEnable(GL_COLOR_SUM_EXT);
2565                 } else {
2566                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
2567                 }
2568                 checkGLcall("glEnable(GL_COLOR_SUM)");
2569               } else {
2570                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2571
2572                 /* for the case of enabled lighting: */
2573                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2574                 checkGLcall("glMaterialfv");
2575
2576                 /* for the case of disabled lighting: */
2577                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2578                   glDisable(GL_COLOR_SUM_EXT);
2579                 } else {
2580                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
2581                 }
2582                 checkGLcall("glDisable(GL_COLOR_SUM)");
2583               }
2584         }
2585         break;
2586
2587     case D3DRS_STENCILENABLE             :
2588         if (Value) {
2589             glEnable(GL_STENCIL_TEST);
2590             checkGLcall("glEnable GL_STENCIL_TEST");
2591         } else {
2592             glDisable(GL_STENCIL_TEST);
2593             checkGLcall("glDisable GL_STENCIL_TEST");
2594         }
2595         break;
2596
2597     case D3DRS_STENCILFUNC               :
2598         {
2599            int glParm = GL_ALWAYS;
2600            int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2601            GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2602
2603            switch ((D3DCMPFUNC) Value) {
2604            case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2605            case D3DCMP_LESS:          glParm=GL_LESS; break;
2606            case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2607            case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2608            case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2609            case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2610            case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2611            case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2612            default:
2613                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2614            }
2615            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2616            This->stencilfunc = glParm;
2617            glStencilFunc(glParm, ref, mask);
2618            checkGLcall("glStencilFunc");
2619         }
2620         break;
2621
2622     case D3DRS_STENCILREF                :
2623         {
2624            int glParm = This->stencilfunc;
2625            int ref = 0;
2626            GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2627
2628            ref = Value;
2629            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2630            glStencilFunc(glParm, ref, mask);
2631            checkGLcall("glStencilFunc");
2632         }
2633         break;
2634
2635     case D3DRS_STENCILMASK               :
2636         {
2637            int glParm = This->stencilfunc;
2638            int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2639            GLuint mask = Value;
2640
2641            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2642            glStencilFunc(glParm, ref, mask);
2643            checkGLcall("glStencilFunc");
2644         }
2645         break;
2646
2647     case D3DRS_STENCILFAIL               :
2648         {
2649             GLenum fail  ; 
2650             GLenum zpass ; 
2651             GLenum zfail ; 
2652
2653             fail = StencilOp(Value);
2654             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2655             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2656             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2657             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2658
2659             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2660             glStencilOp(fail, zfail, zpass);
2661             checkGLcall("glStencilOp(fail, zfail, zpass);");
2662         }
2663         break;
2664     case D3DRS_STENCILZFAIL              :
2665         {
2666             GLenum fail  ; 
2667             GLenum zpass ; 
2668             GLenum zfail ; 
2669
2670             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2671             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2672             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2673             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2674             zfail = StencilOp(Value);
2675
2676             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2677             glStencilOp(fail, zfail, zpass);
2678             checkGLcall("glStencilOp(fail, zfail, zpass);");
2679         }
2680         break;
2681     case D3DRS_STENCILPASS               :
2682         {
2683             GLenum fail  ; 
2684             GLenum zpass ; 
2685             GLenum zfail ; 
2686
2687             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2688             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2689             zpass = StencilOp(Value);
2690             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2691             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2692
2693             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2694             glStencilOp(fail, zfail, zpass);
2695             checkGLcall("glStencilOp(fail, zfail, zpass);");
2696         }
2697         break;
2698
2699     case D3DRS_STENCILWRITEMASK          :
2700         {
2701             glStencilMask(Value);
2702             TRACE("glStencilMask(%lu)\n", Value);
2703             checkGLcall("glStencilMask");
2704         }
2705         break;
2706
2707     case D3DRS_FOGENABLE                 :
2708         {
2709           if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2710                glEnable(GL_FOG);
2711                checkGLcall("glEnable GL_FOG");
2712             } else {
2713                glDisable(GL_FOG);
2714                checkGLcall("glDisable GL_FOG");
2715             }
2716         }
2717         break;
2718
2719     case D3DRS_RANGEFOGENABLE            :
2720         {
2721             if (Value) {
2722               TRACE("Enabled RANGEFOG");
2723             } else {
2724               TRACE("Disabled RANGEFOG");
2725             }
2726         }
2727         break;
2728
2729     case D3DRS_FOGCOLOR                  :
2730         {
2731             float col[4];
2732             D3DCOLORTOGLFLOAT4(Value, col);
2733             /* Set the default alpha blend color */
2734             glFogfv(GL_FOG_COLOR, &col[0]);
2735             checkGLcall("glFog GL_FOG_COLOR");
2736         }
2737         break;
2738
2739     case D3DRS_FOGTABLEMODE              :
2740         { 
2741           glHint(GL_FOG_HINT, GL_NICEST);
2742           switch (Value) {
2743           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2744           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2745           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2746           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2747           default:
2748             FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2749           }
2750           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2751             glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2752           }
2753         }
2754         break;
2755
2756     case D3DRS_FOGVERTEXMODE             :
2757         { 
2758           glHint(GL_FOG_HINT, GL_FASTEST);
2759           switch (Value) {
2760           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2761           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2762           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2763           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2764           default:
2765             FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2766           }
2767           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2768             glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2769           }
2770         }
2771         break;
2772
2773     case D3DRS_FOGSTART                  :
2774         {
2775             tmpvalue.d = Value;
2776             glFogfv(GL_FOG_START, &tmpvalue.f);
2777             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2778             TRACE("Fog Start == %f\n", tmpvalue.f);
2779         }
2780         break;
2781
2782     case D3DRS_FOGEND                    :
2783         {
2784             tmpvalue.d = Value;
2785             glFogfv(GL_FOG_END, &tmpvalue.f);
2786             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2787             TRACE("Fog End == %f\n", tmpvalue.f);
2788         }
2789         break;
2790
2791     case D3DRS_FOGDENSITY                :
2792         {
2793             tmpvalue.d = Value;
2794             glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2795             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2796         }
2797         break;
2798
2799     case D3DRS_VERTEXBLEND               :
2800         {
2801           This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2802           TRACE("Vertex Blending state to %ld\n",  Value);
2803         }
2804         break;
2805
2806     case D3DRS_TWEENFACTOR               :
2807         {
2808           tmpvalue.d = Value;
2809           This->UpdateStateBlock->tween_factor = tmpvalue.f;
2810           TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2811         }
2812         break;
2813
2814     case D3DRS_INDEXEDVERTEXBLENDENABLE  :
2815         {
2816           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2817         }
2818         break;
2819
2820     case D3DRS_COLORVERTEX               :
2821     case D3DRS_DIFFUSEMATERIALSOURCE     :
2822     case D3DRS_SPECULARMATERIALSOURCE    :
2823     case D3DRS_AMBIENTMATERIALSOURCE     :
2824     case D3DRS_EMISSIVEMATERIALSOURCE    :
2825         {
2826             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2827
2828             if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2829                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2830                       This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2831                       This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2832                       This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2833                       This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2834
2835                 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2836                     if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2837                         Parm = GL_AMBIENT_AND_DIFFUSE;
2838                     } else {
2839                         Parm = GL_DIFFUSE;
2840                     }
2841                 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2842                     Parm = GL_AMBIENT;
2843                 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2844                     Parm = GL_EMISSION;
2845                 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2846                     Parm = GL_SPECULAR;
2847                 } else {
2848                     Parm = -1;
2849                 }
2850
2851                 if (Parm == -1) {
2852                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2853                 } else {
2854                     This->tracking_color = NEEDS_TRACKING;
2855                     This->tracking_parm  = Parm;
2856                 }
2857
2858             } else {
2859                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2860             }
2861         }
2862         break; 
2863
2864     case D3DRS_LINEPATTERN               :
2865         {
2866             union {
2867                 DWORD           d;
2868                 D3DLINEPATTERN  lp;
2869             } tmppattern;
2870             tmppattern.d = Value;
2871
2872             TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2873
2874             if (tmppattern.lp.wRepeatFactor) {
2875                 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2876                 checkGLcall("glLineStipple(repeat, linepattern)");
2877                 glEnable(GL_LINE_STIPPLE);
2878                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2879             } else {
2880                 glDisable(GL_LINE_STIPPLE);
2881                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2882             }
2883         }
2884         break;
2885
2886     case D3DRS_ZBIAS                     :
2887         {
2888             if (Value) {
2889                 tmpvalue.d = Value;
2890                 TRACE("ZBias value %f\n", tmpvalue.f);
2891                 glPolygonOffset(0, -tmpvalue.f);
2892                 checkGLcall("glPolygonOffset(0, -Value)");
2893                 glEnable(GL_POLYGON_OFFSET_FILL);
2894                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2895                 glEnable(GL_POLYGON_OFFSET_LINE);
2896                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2897                 glEnable(GL_POLYGON_OFFSET_POINT);
2898                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2899             } else {
2900                 glDisable(GL_POLYGON_OFFSET_FILL);
2901                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2902                 glDisable(GL_POLYGON_OFFSET_LINE);
2903                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2904                 glDisable(GL_POLYGON_OFFSET_POINT);
2905                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2906             }
2907         }
2908         break;
2909
2910     case D3DRS_NORMALIZENORMALS          :
2911         if (Value) {
2912             glEnable(GL_NORMALIZE);
2913             checkGLcall("glEnable(GL_NORMALIZE);");
2914         } else {
2915             glDisable(GL_NORMALIZE);
2916             checkGLcall("glDisable(GL_NORMALIZE);");
2917         }
2918         break;
2919
2920     case D3DRS_POINTSIZE                 :
2921         tmpvalue.d = Value;
2922         TRACE("Set point size to %f\n", tmpvalue.f);
2923         glPointSize(tmpvalue.f);
2924         checkGLcall("glPointSize(...);");
2925         break;
2926
2927     case D3DRS_POINTSIZE_MIN             :
2928         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2929           tmpvalue.d = Value;
2930           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2931           checkGLcall("glPointParameterfEXT(...);");
2932         } else {
2933           FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2934         }
2935         break;
2936
2937     case D3DRS_POINTSIZE_MAX             :
2938         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2939           tmpvalue.d = Value;
2940           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2941           checkGLcall("glPointParameterfEXT(...);");
2942         } else {
2943           FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2944         }
2945         break;
2946
2947     case D3DRS_POINTSCALE_A              :
2948     case D3DRS_POINTSCALE_B              :
2949     case D3DRS_POINTSCALE_C              :
2950     case D3DRS_POINTSCALEENABLE          :
2951         {
2952             /* If enabled, supply the parameters, otherwise fall back to defaults */
2953             if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2954                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2955                 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2956                 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2957                 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2958
2959                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2960                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2961                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2962                 } else {
2963                   TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2964                 }
2965             } else {
2966                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2967                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2968                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2969                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2970                 } else {
2971                   TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2972                 }
2973             }
2974             break;
2975         }
2976
2977     case D3DRS_COLORWRITEENABLE          :
2978       {
2979         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n", 
2980               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
2981               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2982               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
2983               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0); 
2984         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE, 
2985                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2986                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE, 
2987                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2988         checkGLcall("glColorMask(...)");
2989       }
2990       break;
2991
2992     case D3DRS_LOCALVIEWER               :
2993       {
2994         GLint state = (Value) ? 1 : 0;
2995         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);    
2996         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2997       }
2998       break;
2999
3000         /* Unhandled yet...! */
3001     case D3DRS_LASTPIXEL                 :
3002     case D3DRS_ZVISIBLE                  :
3003     case D3DRS_EDGEANTIALIAS             :
3004     case D3DRS_WRAP0                     :
3005     case D3DRS_WRAP1                     :
3006     case D3DRS_WRAP2                     :
3007     case D3DRS_WRAP3                     :
3008     case D3DRS_WRAP4                     :
3009     case D3DRS_WRAP5                     :
3010     case D3DRS_WRAP6                     :
3011     case D3DRS_WRAP7                     :
3012     case D3DRS_SOFTWAREVERTEXPROCESSING  :
3013     case D3DRS_POINTSPRITEENABLE         :
3014     case D3DRS_MULTISAMPLEANTIALIAS      :
3015     case D3DRS_MULTISAMPLEMASK           :
3016     case D3DRS_PATCHEDGESTYLE            :
3017     case D3DRS_PATCHSEGMENTS             :
3018     case D3DRS_DEBUGMONITORTOKEN         :
3019     case D3DRS_POSITIONORDER             :
3020     case D3DRS_NORMALORDER               :
3021         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3022         TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3023         break;
3024     default:
3025         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3026     }
3027
3028     LEAVE_GL();
3029
3030     return D3D_OK;
3031 }
3032 HRESULT  WINAPI  IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3033     ICOM_THIS(IDirect3DDevice8Impl,iface);
3034     TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3035     *pValue = This->StateBlock->renderstate[State];
3036     return D3D_OK;
3037 }
3038 HRESULT  WINAPI  IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3039   ICOM_THIS(IDirect3DDevice8Impl,iface);
3040   
3041   TRACE("(%p)\n", This);
3042   
3043   return IDirect3DDeviceImpl_BeginStateBlock(This);
3044 }
3045 HRESULT  WINAPI  IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3046   IDirect3DStateBlockImpl* pSB;
3047   ICOM_THIS(IDirect3DDevice8Impl,iface);
3048   HRESULT res;
3049
3050   TRACE("(%p)\n", This);
3051
3052   res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3053   *pToken = (DWORD) pSB;
3054   return res;
3055 }
3056
3057 HRESULT  WINAPI  IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3058   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3059   ICOM_THIS(IDirect3DDevice8Impl,iface);
3060
3061   TRACE("(%p)\n", This);
3062
3063   return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3064
3065 }
3066 HRESULT  WINAPI  IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3067   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3068   ICOM_THIS(IDirect3DDevice8Impl,iface);
3069
3070   TRACE("(%p)\n", This);
3071
3072   return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3073 }
3074 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3075   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3076   ICOM_THIS(IDirect3DDevice8Impl,iface);
3077
3078   TRACE("(%p)\n", This);
3079
3080   return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3081 }
3082
3083 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3084   IDirect3DStateBlockImpl* pSB;
3085   ICOM_THIS(IDirect3DDevice8Impl,iface);
3086   HRESULT res;
3087
3088   TRACE("(%p) : for type %d\n", This, Type);
3089
3090   res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3091   *pToken = (DWORD) pSB;
3092   return res;
3093 }
3094
3095 HRESULT  WINAPI  IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3096     ICOM_THIS(IDirect3DDevice8Impl,iface);
3097     FIXME("(%p) : stub\n", This);    return D3D_OK;
3098 }
3099 HRESULT  WINAPI  IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3100     ICOM_THIS(IDirect3DDevice8Impl,iface);
3101     FIXME("(%p) : stub\n", This);    return D3D_OK;
3102 }
3103 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3104     ICOM_THIS(IDirect3DDevice8Impl,iface);
3105     TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3106     *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3107     if (*ppTexture)
3108         IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3109     return D3D_OK;
3110 }
3111 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3112
3113     IDirect3DBaseTexture8 *oldTxt;
3114     BOOL reapplyStates = TRUE;
3115     DWORD oldTextureDimensions = -1;
3116     DWORD reapplyFlags = 0;
3117
3118     ICOM_THIS(IDirect3DDevice8Impl,iface);
3119     D3DRESOURCETYPE textureType;
3120
3121     oldTxt = This->UpdateStateBlock->textures[Stage];
3122     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3123
3124     /* Reject invalid texture units */
3125     if (Stage >= GL_LIMITS(textures)) {
3126         TRACE("Attempt to access invalid texture rejected\n");
3127         return D3DERR_INVALIDCALL;
3128     }
3129
3130     This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3131     This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3132     This->UpdateStateBlock->textures[Stage] = pTexture;
3133
3134     /* Handle recording of state blocks */
3135     if (This->isRecordingState) {
3136         TRACE("Recording... not performing anything\n");
3137         return D3D_OK;
3138     }
3139
3140     oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3141     ENTER_GL();
3142
3143     /* Make appropriate texture active */
3144     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3145 #if defined(GL_VERSION_1_3)
3146         glActiveTexture(GL_TEXTURE0 + Stage);
3147         checkGLcall("glActiveTexture");
3148 #else
3149         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3150         checkGLcall("glActiveTextureARB");
3151 #endif
3152     } else if (Stage>0) {
3153         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3154     }
3155
3156     /* Decrement the count of the previous texture */
3157     if (NULL != oldTxt) {
3158         IDirect3DBaseTexture8Impl_Release(oldTxt);
3159     }
3160
3161     if (NULL != pTexture) {
3162         IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3163
3164         /* Now setup the texture appropraitly */
3165         textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3166
3167         if (textureType == D3DRTYPE_TEXTURE) {
3168           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3169             TRACE("Skipping setting texture as old == new\n");
3170             reapplyStates = FALSE;
3171           } else {
3172             /* Standard 2D texture */
3173             TRACE("Standard 2d texture\n");
3174             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3175
3176             /* Load up the texture now */
3177             IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3178           }
3179         } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3180           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3181             TRACE("Skipping setting texture as old == new\n");
3182             reapplyStates = FALSE;
3183           } else {
3184             /* Standard 3D (volume) texture */
3185             TRACE("Standard 3d texture\n");
3186             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3187
3188             /* Load up the texture now */
3189             IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3190           }
3191         } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3192           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3193             TRACE("Skipping setting texture as old == new\n");
3194             reapplyStates = FALSE;
3195           } else {
3196             /* Standard Cube texture */
3197             TRACE("Standard Cube texture\n");
3198             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3199
3200             /* Load up the texture now */
3201             IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3202           }
3203         } else {
3204             FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3205         }
3206     } else {
3207         TRACE("Setting to no texture (ie default texture)\n");
3208         This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3209         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3210         checkGLcall("glBindTexture");
3211         TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3212     }
3213
3214     /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3215     if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3216        glDisable(oldTextureDimensions);
3217        checkGLcall("Disable oldTextureDimensions");
3218        if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3219           glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3220           checkGLcall("glEnable new texture dimensions");
3221        }
3222
3223        /* If Alpha arg1 is texture then handle the special case when there changes between a
3224           texture and no texture - See comments in set_tex_op                                  */
3225        if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) && 
3226            (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3227        {
3228            reapplyFlags |= REAPPLY_ALPHAOP;
3229        }
3230     }
3231
3232
3233     /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3234        a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3235     if (reapplyStates) {
3236        setupTextureStates(iface, Stage, reapplyFlags);
3237     }
3238
3239     LEAVE_GL();   
3240
3241     return D3D_OK;
3242 }
3243
3244 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3245     ICOM_THIS(IDirect3DDevice8Impl,iface);
3246     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3247     *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3248     return D3D_OK;
3249 }
3250
3251 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3252     ICOM_THIS(IDirect3DDevice8Impl,iface);
3253     union {
3254         float f;
3255         DWORD d;
3256     } tmpvalue;
3257
3258     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3259    
3260     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3261
3262     /* Reject invalid texture units */
3263     if (Stage >= GL_LIMITS(textures)) {
3264         TRACE("Attempt to access invalid texture rejected\n");
3265         return D3DERR_INVALIDCALL;
3266     }
3267
3268     This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3269     This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3270     This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3271
3272     /* Handle recording of state blocks */
3273     if (This->isRecordingState) {
3274         TRACE("Recording... not performing anything\n");
3275         return D3D_OK;
3276     }
3277
3278     ENTER_GL();
3279
3280     /* Make appropriate texture active */
3281     VTRACE(("Activating appropriate texture state %ld\n", Stage));
3282     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3283 #if defined(GL_VERSION_1_3)
3284         glActiveTexture(GL_TEXTURE0 + Stage);
3285         vcheckGLcall("glActiveTexture");
3286 #else
3287         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3288         vcheckGLcall("glActiveTextureARB");
3289 #endif
3290     } else if (Stage > 0) {
3291         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3292     }
3293
3294     switch (Type) {
3295
3296     case D3DTSS_MINFILTER             :
3297     case D3DTSS_MIPFILTER             :
3298         {
3299             DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3300             DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3301             GLint realVal = GL_LINEAR;
3302
3303             if (ValueMIN == D3DTEXF_NONE) {
3304               /* Doesn't really make sense - Windows just seems to disable
3305                  mipmapping when this occurs                              */
3306               FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3307               realVal = GL_LINEAR;
3308             } else if (ValueMIN == D3DTEXF_POINT) {
3309                 /* GL_NEAREST_* */
3310               if (ValueMIP == D3DTEXF_NONE) {
3311                     realVal = GL_NEAREST;
3312                 } else if (ValueMIP == D3DTEXF_POINT) {
3313                     realVal = GL_NEAREST_MIPMAP_NEAREST;
3314                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3315                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3316                 } else {
3317                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3318                     realVal = GL_NEAREST;
3319                 }
3320             } else if (ValueMIN == D3DTEXF_LINEAR) {
3321                 /* GL_LINEAR_* */
3322                 if (ValueMIP == D3DTEXF_NONE) {
3323                     realVal = GL_LINEAR;
3324                 } else if (ValueMIP == D3DTEXF_POINT) {
3325                     realVal = GL_LINEAR_MIPMAP_NEAREST;
3326                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3327                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3328                 } else {
3329                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3330                     realVal = GL_LINEAR;
3331                 }
3332             } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3333               if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3334                 if (ValueMIP == D3DTEXF_NONE) {
3335                   realVal = GL_LINEAR_MIPMAP_LINEAR;              
3336                 } else if (ValueMIP == D3DTEXF_POINT) {
3337                   realVal = GL_LINEAR_MIPMAP_NEAREST;
3338                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3339                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3340                 } else {
3341                   FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3342                   realVal = GL_LINEAR;
3343                 }
3344               } else {
3345                 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3346                 realVal = GL_LINEAR;
3347               }
3348             } else {
3349                 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3350                 realVal = GL_LINEAR_MIPMAP_LINEAR;
3351             }
3352
3353             TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3354             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3355             checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3356             /**
3357              * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3358              */
3359             if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3360               glTexParameteri(This->StateBlock->textureDimensions[Stage], 
3361                               GL_TEXTURE_MAX_ANISOTROPY_EXT, 
3362                               This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3363               checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3364             }
3365         }
3366         break;
3367
3368     case D3DTSS_MAGFILTER             :
3369       {
3370         DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3371         GLint realVal = GL_NEAREST;
3372
3373         if (ValueMAG == D3DTEXF_POINT) {
3374           realVal = GL_NEAREST;
3375         } else if (ValueMAG == D3DTEXF_LINEAR) {
3376           realVal = GL_LINEAR;
3377         } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3378           if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3379             realVal = GL_LINEAR;
3380           } else {
3381             FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3382             realVal = GL_NEAREST;
3383           }
3384         } else {
3385           FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3386           realVal = GL_NEAREST;
3387         }
3388         TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3389         glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3390         checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3391         /**
3392          * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3393          */
3394         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3395           glTexParameteri(This->StateBlock->textureDimensions[Stage], 
3396                           GL_TEXTURE_MAX_ANISOTROPY_EXT, 
3397                           This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3398           checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3399         }
3400       }
3401       break;
3402
3403     case D3DTSS_MAXMIPLEVEL           :
3404       {
3405         /**
3406          * Not really the same, but the more apprioprate than nothing
3407          */
3408         glTexParameteri(This->StateBlock->textureDimensions[Stage], 
3409                         GL_TEXTURE_BASE_LEVEL, 
3410                         This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3411         checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3412       }
3413       break;
3414
3415     case D3DTSS_MAXANISOTROPY         :
3416       { 
3417         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3418           glTexParameteri(This->StateBlock->textureDimensions[Stage], 
3419                           GL_TEXTURE_MAX_ANISOTROPY_EXT, 
3420                           This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3421           checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3422         }
3423       }
3424       break;
3425
3426     case D3DTSS_MIPMAPLODBIAS         :
3427       { 
3428         if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3429           tmpvalue.d = Value;
3430           glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, 
3431                     GL_TEXTURE_LOD_BIAS_EXT,
3432                     tmpvalue.f);
3433           checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3434         }
3435       }
3436       break;
3437
3438     case D3DTSS_ALPHAOP               :
3439     case D3DTSS_COLOROP               :
3440         {
3441
3442             if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3443                 /* TODO: Disable by making this and all later levels disabled */
3444                 glDisable(GL_TEXTURE_1D);
3445                 checkGLcall("Disable GL_TEXTURE_1D");
3446                 glDisable(GL_TEXTURE_2D);
3447                 checkGLcall("Disable GL_TEXTURE_2D");
3448                 glDisable(GL_TEXTURE_3D);
3449                 checkGLcall("Disable GL_TEXTURE_3D");
3450                 break; /* Don't bother setting the texture operations */
3451             } else {
3452                 /* Enable only the appropriate texture dimension */
3453                 if (Type == D3DTSS_COLOROP) {
3454                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3455                         glEnable(GL_TEXTURE_1D);
3456                         checkGLcall("Enable GL_TEXTURE_1D");
3457                     } else {
3458                         glDisable(GL_TEXTURE_1D);
3459                         checkGLcall("Disable GL_TEXTURE_1D");
3460                     } 
3461                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3462                       if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3463                         glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3464                         checkGLcall("Enable GL_TEXTURE_2D");
3465                       } else {
3466                         glEnable(GL_TEXTURE_2D);
3467                         checkGLcall("Enable GL_TEXTURE_2D");
3468                       }
3469                     } else {
3470                         glDisable(GL_TEXTURE_2D);
3471                         checkGLcall("Disable GL_TEXTURE_2D");
3472                     }
3473                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3474                         glEnable(GL_TEXTURE_3D);
3475                         checkGLcall("Enable GL_TEXTURE_3D");
3476                     } else {
3477                         glDisable(GL_TEXTURE_3D);
3478                         checkGLcall("Disable GL_TEXTURE_3D");
3479                     }
3480                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3481                         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3482                         checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3483                     } else {
3484                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3485                         checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3486                     }
3487                 }
3488             }
3489             /* Drop through... (Except disable case) */
3490         case D3DTSS_COLORARG0             :
3491         case D3DTSS_COLORARG1             :
3492         case D3DTSS_COLORARG2             :
3493         case D3DTSS_ALPHAARG0             :
3494         case D3DTSS_ALPHAARG1             :
3495         case D3DTSS_ALPHAARG2             :
3496             {
3497                 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 || 
3498                                    Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3499                 if (isAlphaArg) {
3500                     set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3501                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1], 
3502                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2], 
3503                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3504                 } else {
3505                     set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3506                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1], 
3507                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2], 
3508                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3509                 }
3510             }
3511             break;
3512         }
3513
3514     case D3DTSS_ADDRESSU              :
3515     case D3DTSS_ADDRESSV              :
3516     case D3DTSS_ADDRESSW              :
3517         {
3518             GLint wrapParm = GL_REPEAT;
3519
3520             switch (Value) {
3521             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
3522             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;      
3523             case D3DTADDRESS_BORDER: 
3524               {
3525                 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3526                   wrapParm = GL_CLAMP_TO_BORDER_ARB; 
3527                 } else {
3528                   /* FIXME: Not right, but better */
3529                   FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3530                   wrapParm = GL_REPEAT; 
3531                 }
3532               }
3533               break;
3534             case D3DTADDRESS_MIRROR: 
3535               {
3536                 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3537                   wrapParm = GL_MIRRORED_REPEAT_ARB;
3538                 } else {
3539                   /* Unsupported in OpenGL pre-1.4 */
3540                   FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3541                   wrapParm = GL_REPEAT;
3542                 }
3543               }
3544               break;
3545             case D3DTADDRESS_MIRRORONCE: 
3546               {
3547                 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3548                   wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3549                 } else {
3550                   FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3551                   wrapParm = GL_REPEAT; 
3552                 }
3553               }
3554               break;
3555
3556             default:
3557                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3558                 wrapParm = GL_REPEAT; 
3559             }
3560
3561             switch (Type) {
3562             case D3DTSS_ADDRESSU:
3563                 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3564                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3565                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3566                 break;
3567             case D3DTSS_ADDRESSV:
3568                 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3569                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3570                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3571                 break;
3572             case D3DTSS_ADDRESSW:
3573                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3574                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3575                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3576                 break;
3577             default: /* nop */
3578                 break; /** stupic compilator */
3579             }
3580         }
3581         break;
3582
3583     case D3DTSS_BORDERCOLOR           :
3584         {
3585             float col[4];
3586             D3DCOLORTOGLFLOAT4(Value, col);
3587             TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value); 
3588             glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3589             checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3590         }
3591         break;
3592
3593     case D3DTSS_TEXCOORDINDEX         :
3594         {
3595             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3596
3597             /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include 
3598                   one flag, you can still specify an index value, which the system uses to 
3599                   determine the texture wrapping mode.  
3600                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3601                   means use the vertex position (camera-space) as the input texture coordinates 
3602                   for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render 
3603                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3604                   to the TEXCOORDINDEX value */
3605           
3606             /** 
3607              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos 
3608              */
3609             switch (Value & 0xFFFF0000) {
3610             case D3DTSS_TCI_PASSTHRU:
3611               /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3612               glDisable(GL_TEXTURE_GEN_S);
3613               glDisable(GL_TEXTURE_GEN_T);
3614               glDisable(GL_TEXTURE_GEN_R);
3615               checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3616               break;
3617
3618             case D3DTSS_TCI_CAMERASPACEPOSITION:
3619               /* CameraSpacePosition means use the vertex position, transformed to camera space, 
3620                  as the input texture coordinates for this stage's texture transformation. This 
3621                  equates roughly to EYE_LINEAR                                                  */
3622               {
3623                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3624                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3625                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3626                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3627                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3628
3629                 glMatrixMode(GL_MODELVIEW);
3630                 glPushMatrix();
3631                 glLoadIdentity();
3632                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3633                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3634                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3635                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3636                 glPopMatrix();
3637                 
3638                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3639                 glEnable(GL_TEXTURE_GEN_S);
3640                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3641                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3642                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3643                 glEnable(GL_TEXTURE_GEN_T);
3644                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3645                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3646                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3647                 glEnable(GL_TEXTURE_GEN_R);
3648                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3649                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3650                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3651               }
3652               break;
3653
3654             case D3DTSS_TCI_CAMERASPACENORMAL:
3655               {
3656                 if (GL_SUPPORT(GL_NV_texgen_reflection)) {
3657                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3658                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3659                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3660                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3661                   TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3662
3663                   glMatrixMode(GL_MODELVIEW);
3664                   glPushMatrix();
3665                   glLoadIdentity();
3666                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3667                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3668                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3669                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3670                   glPopMatrix();
3671                   
3672                   glEnable(GL_TEXTURE_GEN_S);
3673                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3674                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3675                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3676                   glEnable(GL_TEXTURE_GEN_T);
3677                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3678                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3679                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3680                   glEnable(GL_TEXTURE_GEN_R);
3681                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3682                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3683                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3684                 }
3685               }
3686               break;
3687
3688             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3689               {
3690                 if (GL_SUPPORT(GL_NV_texgen_reflection)) {
3691                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3692                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3693                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3694                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3695                   TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3696                   
3697                   glMatrixMode(GL_MODELVIEW);
3698                   glPushMatrix();
3699                   glLoadIdentity();
3700                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3701                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3702                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3703                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3704                   glPopMatrix();
3705                   
3706                   glEnable(GL_TEXTURE_GEN_S);
3707                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3708                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3709                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3710                   glEnable(GL_TEXTURE_GEN_T);
3711                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3712                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3713                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3714                   glEnable(GL_TEXTURE_GEN_R);
3715                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3716                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3717                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3718                 }
3719               }
3720               break;
3721
3722             /* Unhandled types: */
3723             default:
3724                 /* Todo: */
3725                 /* ? disable GL_TEXTURE_GEN_n ? */ 
3726                 glDisable(GL_TEXTURE_GEN_S);
3727                 glDisable(GL_TEXTURE_GEN_T);
3728                 glDisable(GL_TEXTURE_GEN_R);
3729                 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3730                 break;
3731             }
3732         }
3733         break;
3734
3735         /* Unhandled */
3736     case D3DTSS_TEXTURETRANSFORMFLAGS :
3737         set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3738         break; 
3739
3740     case D3DTSS_BUMPENVMAT00          :
3741     case D3DTSS_BUMPENVMAT01          :
3742         TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3743         break;
3744     case D3DTSS_BUMPENVMAT10          :
3745     case D3DTSS_BUMPENVMAT11          :
3746         TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3747         break;
3748
3749     case D3DTSS_BUMPENVLSCALE         :
3750       TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3751       break;
3752
3753     case D3DTSS_BUMPENVLOFFSET        :
3754       TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3755       break;
3756
3757     case D3DTSS_RESULTARG             :
3758       TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3759       break;
3760
3761     default:
3762         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3763         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3764     }
3765
3766     LEAVE_GL();
3767
3768     return D3D_OK;
3769 }
3770 HRESULT  WINAPI  IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3771     ICOM_THIS(IDirect3DDevice8Impl,iface);
3772     TRACE("(%p) : stub\n", This);    /* FIXME: Needs doing, but called often and is harmless */
3773     return D3D_OK;
3774 }
3775 HRESULT  WINAPI  IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3776     ICOM_THIS(IDirect3DDevice8Impl,iface);
3777     FIXME("(%p) : stub\n", This);    
3778     return D3D_OK;
3779 }
3780 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3781     ICOM_THIS(IDirect3DDevice8Impl,iface);
3782     FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3783           pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3784     if (PaletteNumber >= MAX_PALETTES) {
3785         return D3DERR_INVALIDCALL;
3786     }
3787     memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3788     return D3D_OK;
3789 }
3790 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3791     ICOM_THIS(IDirect3DDevice8Impl,iface);
3792     if (PaletteNumber >= MAX_PALETTES) {
3793         return D3DERR_INVALIDCALL;
3794     }
3795     memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3796     FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3797           pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3798     return D3D_OK;
3799 }
3800 HRESULT  WINAPI  IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3801     ICOM_THIS(IDirect3DDevice8Impl,iface);
3802     FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3803     if (PaletteNumber >= MAX_PALETTES) {
3804         return D3DERR_INVALIDCALL;
3805     }
3806     This->currentPalette = PaletteNumber;
3807
3808 #if defined(GL_EXT_paletted_texture)
3809     if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3810
3811       ENTER_GL();
3812
3813       GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D,    /* target */
3814                                   GL_RGBA,          /* internal format */
3815                                   256,              /* table size */
3816                                   GL_RGBA,          /* table format */
3817                                   GL_UNSIGNED_BYTE, /* table type */
3818                                   This->palettes[PaletteNumber]);
3819       checkGLcall("glColorTableEXT");
3820
3821       LEAVE_GL();
3822
3823     } else {
3824       /* Delayed palette handling ... waiting for software emulation into preload code */
3825     }
3826 #endif
3827     return D3D_OK;
3828 }
3829 HRESULT  WINAPI  IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3830     ICOM_THIS(IDirect3DDevice8Impl,iface);
3831     *PaletteNumber = This->currentPalette;
3832     FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3833     return D3D_OK;
3834 }
3835 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3836
3837     ICOM_THIS(IDirect3DDevice8Impl,iface);
3838     This->StateBlock->streamIsUP = FALSE;
3839
3840     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3841     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3842
3843     return D3D_OK;
3844 }
3845 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3846                                                            UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3847     UINT idxStride = 2;
3848     IDirect3DIndexBuffer8      *pIB;
3849     D3DINDEXBUFFER_DESC         IdxBufDsc;
3850
3851     ICOM_THIS(IDirect3DDevice8Impl,iface);
3852     pIB = This->StateBlock->pIndexData;
3853     This->StateBlock->streamIsUP = FALSE;
3854
3855     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, 
3856           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3857           minIndex, NumVertices, startIndex, primCount);
3858
3859     IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3860     if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3861         idxStride = 2;
3862     } else {
3863         idxStride = 4;
3864     }
3865
3866     drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3867                    minIndex);
3868
3869     return D3D_OK;
3870 }
3871 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3872     ICOM_THIS(IDirect3DDevice8Impl,iface);
3873
3874     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), 
3875           PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3876
3877     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3878
3879     /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3880     This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData; 
3881     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3882     This->StateBlock->streamIsUP = TRUE;
3883     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3884     This->StateBlock->stream_stride[0] = 0;
3885     This->StateBlock->stream_source[0] = NULL;
3886
3887     /*stream zero settings set to null at end */
3888     return D3D_OK;
3889 }
3890 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3891                                                              UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3892                                                              D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3893                                                              UINT VertexStreamZeroStride) {
3894     int idxStride;
3895     ICOM_THIS(IDirect3DDevice8Impl,iface);
3896     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),
3897           MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,  IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3898
3899     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3900     if (IndexDataFormat == D3DFMT_INDEX16) {
3901         idxStride = 2;
3902     } else {
3903         idxStride = 4;
3904     }
3905
3906     /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3907     This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3908     This->StateBlock->streamIsUP = TRUE;
3909     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3910     drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3911
3912     /*stream zero settings set to null at end */
3913     This->StateBlock->stream_source[0] = NULL;
3914     This->StateBlock->stream_stride[0] = 0;
3915     IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3916
3917     return D3D_OK;
3918 }
3919 HRESULT  WINAPI  IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3920     ICOM_THIS(IDirect3DDevice8Impl,iface);
3921     FIXME("(%p) : stub\n", This);    return D3D_OK;
3922 }
3923 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3924     ICOM_THIS(IDirect3DDevice8Impl,iface);
3925     IDirect3DVertexShaderImpl* object;
3926     IDirect3DVertexShaderDeclarationImpl* attached_decl;
3927     HRESULT res;
3928     UINT i;
3929
3930     TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3931     if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3932       return D3DERR_INVALIDCALL;
3933     }
3934     for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3935     if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3936       return D3DERR_OUTOFVIDEOMEMORY;
3937     }
3938
3939     /** Create the Vertex Shader */
3940     res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3941     /** TODO: check FAILED(res) */
3942
3943     /** Create and Bind the Vertex Shader Declaration */
3944     res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3945     /** TODO: check FAILED(res) */
3946
3947     VertexShaders[i] = object;
3948     VertexShaderDeclarations[i] = attached_decl;
3949     *pHandle = VS_HIGHESTFIXEDFXF + i;
3950     TRACE("Finished creating vertex shader %lx\n", *pHandle);
3951
3952     return D3D_OK;
3953 }
3954 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3955     ICOM_THIS(IDirect3DDevice8Impl,iface);
3956
3957     This->UpdateStateBlock->VertexShader = Handle;
3958     This->UpdateStateBlock->Changed.vertexShader = TRUE;
3959     This->UpdateStateBlock->Set.vertexShader = TRUE;
3960     
3961     if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3962       TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3963       This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3964       This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3965       This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3966     } else { /* use a fvf, so desactivate the vshader decl */
3967       TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3968       This->UpdateStateBlock->vertexShaderDecl = NULL;
3969       This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3970       This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3971     }
3972     /* Handle recording of state blocks */
3973     if (This->isRecordingState) {
3974       TRACE("Recording... not performing anything\n");
3975       return D3D_OK;
3976     }
3977     /**
3978      * TODO: merge HAL shaders context switching from prototype
3979      */
3980     return D3D_OK;
3981 }
3982 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3983     ICOM_THIS(IDirect3DDevice8Impl,iface);
3984     TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3985     *pHandle = This->StateBlock->VertexShader;
3986     return D3D_OK;
3987 }
3988
3989 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3990     ICOM_THIS(IDirect3DDevice8Impl,iface);
3991     IDirect3DVertexShaderImpl* object; 
3992     IDirect3DVertexShaderDeclarationImpl* attached_decl;
3993
3994     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3995       return D3DERR_INVALIDCALL;
3996     }
3997
3998     /**
3999      * Delete Vertex Shader
4000      */
4001     object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4002     if (NULL == object) {
4003       return D3DERR_INVALIDCALL;
4004     }
4005     TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4006     /* TODO: check validity of object */
4007     if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4008     if (object->prgId != 0) {
4009         GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4010     }
4011     HeapFree(GetProcessHeap(), 0, (void *)object->data);
4012     HeapFree(GetProcessHeap(), 0, (void *)object);
4013     VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4014
4015     /**
4016      * Delete Vertex Shader Declaration
4017      */
4018     attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4019     if (NULL == attached_decl) {
4020       return D3DERR_INVALIDCALL;
4021     } 
4022     TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4023     /* TODO: check validity of object */
4024     HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4025     HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4026     VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4027
4028     return D3D_OK;
4029 }
4030
4031 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4032   ICOM_THIS(IDirect3DDevice8Impl,iface);
4033
4034   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4035     ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4036     return D3DERR_INVALIDCALL;
4037   }
4038   if (NULL == pConstantData) {
4039     return D3DERR_INVALIDCALL;
4040   }
4041   if (ConstantCount > 1) {
4042     FLOAT* f = (FLOAT*)pConstantData;
4043     UINT i;
4044     TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4045     for (i = 0; i < ConstantCount; ++i) {
4046       TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4047       f += 4;
4048     }
4049   } else { 
4050     FLOAT* f = (FLOAT*) pConstantData;
4051     TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4052   }
4053   This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4054   memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4055   return D3D_OK;
4056 }
4057 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4058   ICOM_THIS(IDirect3DDevice8Impl,iface);
4059
4060   TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4061   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4062     return D3DERR_INVALIDCALL;
4063   }
4064   if (NULL == pConstantData) {
4065     return D3DERR_INVALIDCALL;
4066   }
4067   memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4068   return D3D_OK;
4069 }
4070 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4071   /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4072   IDirect3DVertexShaderDeclarationImpl* attached_decl;
4073   
4074   attached_decl = VERTEX_SHADER_DECL(Handle);
4075   if (NULL == attached_decl) {
4076     return D3DERR_INVALIDCALL;
4077   }
4078   return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4079 }
4080 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4081   /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4082   IDirect3DVertexShaderImpl* object;
4083   
4084   object = VERTEX_SHADER(Handle);
4085   if (NULL == object) {
4086     return D3DERR_INVALIDCALL;
4087   }
4088   return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4089 }
4090
4091 HRESULT  WINAPI  IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4092     ICOM_THIS(IDirect3DDevice8Impl,iface);
4093     IDirect3DIndexBuffer8 *oldIdxs;
4094
4095     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4096     oldIdxs = This->StateBlock->pIndexData;
4097
4098     This->UpdateStateBlock->Changed.Indices = TRUE;
4099     This->UpdateStateBlock->Set.Indices = TRUE;
4100     This->UpdateStateBlock->pIndexData = pIndexData;
4101     This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4102
4103     /* Handle recording of state blocks */
4104     if (This->isRecordingState) {
4105         TRACE("Recording... not performing anything\n");
4106         return D3D_OK;
4107     }
4108
4109     if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4110     if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4111     return D3D_OK;
4112 }
4113 HRESULT  WINAPI  IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4114     ICOM_THIS(IDirect3DDevice8Impl,iface);
4115     FIXME("(%p) : stub\n", This);
4116
4117     *ppIndexData = This->StateBlock->pIndexData;
4118     /* up ref count on ppindexdata */
4119     if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4120     *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4121
4122     return D3D_OK;
4123 }
4124 HRESULT  WINAPI  IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4125     ICOM_THIS(IDirect3DDevice8Impl,iface);
4126     IDirect3DPixelShaderImpl* object;
4127     HRESULT res;
4128     UINT i;
4129
4130     TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4131     if (NULL == pFunction || NULL == pHandle) {
4132       return D3DERR_INVALIDCALL;
4133     }
4134     for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4135     if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4136       return D3DERR_OUTOFVIDEOMEMORY;
4137     }
4138
4139     /** Create the Pixel Shader */
4140     res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4141     if (SUCCEEDED(res)) {
4142       PixelShaders[i] = object;
4143       *pHandle = VS_HIGHESTFIXEDFXF + i;
4144       return D3D_OK;
4145     } 
4146     *pHandle = 0xFFFFFFFF;
4147     return res;
4148 }
4149 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4150     ICOM_THIS(IDirect3DDevice8Impl,iface);
4151
4152     This->UpdateStateBlock->PixelShader = Handle;
4153     This->UpdateStateBlock->Changed.pixelShader = TRUE;
4154     This->UpdateStateBlock->Set.pixelShader = TRUE;
4155
4156     /* Handle recording of state blocks */
4157     if (This->isRecordingState) {
4158         TRACE_(d3d_shader)("Recording... not performing anything\n");
4159         return D3D_OK;
4160     }
4161
4162     /* FIXME: Quieten when not being used */
4163     if (Handle != 0) {
4164       FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4165     } else {
4166       TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4167     }
4168
4169     return D3D_OK;
4170 }
4171 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4172     ICOM_THIS(IDirect3DDevice8Impl,iface);
4173     TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4174     *pHandle = This->StateBlock->PixelShader;
4175     return D3D_OK;
4176 }
4177
4178 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4179     ICOM_THIS(IDirect3DDevice8Impl,iface);
4180     IDirect3DPixelShaderImpl* object;   
4181
4182     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4183       return D3DERR_INVALIDCALL;
4184     }
4185     object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4186     TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4187     /* TODO: check validity of object before free */
4188     if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4189     HeapFree(GetProcessHeap(), 0, (void *)object->data);
4190     HeapFree(GetProcessHeap(), 0, (void *)object);
4191     PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4192
4193     return D3D_OK;
4194 }
4195
4196 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4197   ICOM_THIS(IDirect3DDevice8Impl,iface);
4198
4199   if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4200     ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4201     return D3DERR_INVALIDCALL;
4202   }
4203   if (NULL == pConstantData) {
4204     return D3DERR_INVALIDCALL;
4205   }
4206   if (ConstantCount > 1) {
4207     FLOAT* f = (FLOAT*)pConstantData;
4208     UINT i;
4209     TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4210     for (i = 0; i < ConstantCount; ++i) {
4211       TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4212       f += 4;
4213     }
4214   } else { 
4215     FLOAT* f = (FLOAT*) pConstantData;
4216     TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4217   }
4218   This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4219   memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4220   return D3D_OK;
4221 }
4222 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4223   ICOM_THIS(IDirect3DDevice8Impl,iface);
4224
4225   TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4226   if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4227     return D3DERR_INVALIDCALL;
4228   }
4229   if (NULL == pConstantData) {
4230     return D3DERR_INVALIDCALL;
4231   }
4232   memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4233   return D3D_OK;
4234 }
4235 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4236     IDirect3DPixelShaderImpl* object;
4237
4238     object = PIXEL_SHADER(Handle);
4239     if (NULL == object) {
4240       return D3DERR_INVALIDCALL;
4241     } 
4242     return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4243 }
4244 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4245     ICOM_THIS(IDirect3DDevice8Impl,iface);
4246     FIXME("(%p) : stub\n", This);    return D3D_OK;
4247 }
4248 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4249     ICOM_THIS(IDirect3DDevice8Impl,iface);
4250     FIXME("(%p) : stub\n", This);    return D3D_OK;
4251 }
4252 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4253     ICOM_THIS(IDirect3DDevice8Impl,iface);
4254     FIXME("(%p) : stub\n", This);    return D3D_OK;
4255 }
4256
4257 HRESULT  WINAPI  IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4258     IDirect3DVertexBuffer8 *oldSrc;
4259     ICOM_THIS(IDirect3DDevice8Impl,iface);
4260
4261     oldSrc = This->StateBlock->stream_source[StreamNumber];
4262     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4263
4264     This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4265     This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4266     This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4267     This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4268
4269     /* Handle recording of state blocks */
4270     if (This->isRecordingState) {
4271         TRACE("Recording... not performing anything\n");
4272         return D3D_OK;
4273     }
4274
4275     if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4276     if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4277     return D3D_OK;
4278 }
4279 HRESULT  WINAPI  IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4280     ICOM_THIS(IDirect3DDevice8Impl,iface);
4281     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4282     *pStream = This->StateBlock->stream_source[StreamNumber];
4283     *pStride = This->StateBlock->stream_stride[StreamNumber];
4284     IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4285     return D3D_OK;
4286 }
4287
4288
4289 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4290 {
4291     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4292     IDirect3DDevice8Impl_QueryInterface,
4293     IDirect3DDevice8Impl_AddRef,
4294     IDirect3DDevice8Impl_Release,
4295     IDirect3DDevice8Impl_TestCooperativeLevel,
4296     IDirect3DDevice8Impl_GetAvailableTextureMem,
4297     IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4298     IDirect3DDevice8Impl_GetDirect3D,
4299     IDirect3DDevice8Impl_GetDeviceCaps,
4300     IDirect3DDevice8Impl_GetDisplayMode,
4301     IDirect3DDevice8Impl_GetCreationParameters,
4302     IDirect3DDevice8Impl_SetCursorProperties,
4303     IDirect3DDevice8Impl_SetCursorPosition,
4304     IDirect3DDevice8Impl_ShowCursor,
4305     IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4306     IDirect3DDevice8Impl_Reset,
4307     IDirect3DDevice8Impl_Present,
4308     IDirect3DDevice8Impl_GetBackBuffer,
4309     IDirect3DDevice8Impl_GetRasterStatus,
4310     IDirect3DDevice8Impl_SetGammaRamp,
4311     IDirect3DDevice8Impl_GetGammaRamp,
4312     IDirect3DDevice8Impl_CreateTexture,
4313     IDirect3DDevice8Impl_CreateVolumeTexture,
4314     IDirect3DDevice8Impl_CreateCubeTexture,
4315     IDirect3DDevice8Impl_CreateVertexBuffer,
4316     IDirect3DDevice8Impl_CreateIndexBuffer,
4317     IDirect3DDevice8Impl_CreateRenderTarget,
4318     IDirect3DDevice8Impl_CreateDepthStencilSurface,
4319     IDirect3DDevice8Impl_CreateImageSurface,
4320     IDirect3DDevice8Impl_CopyRects,
4321     IDirect3DDevice8Impl_UpdateTexture,
4322     IDirect3DDevice8Impl_GetFrontBuffer,
4323     IDirect3DDevice8Impl_SetRenderTarget,
4324     IDirect3DDevice8Impl_GetRenderTarget,
4325     IDirect3DDevice8Impl_GetDepthStencilSurface,
4326     IDirect3DDevice8Impl_BeginScene,
4327     IDirect3DDevice8Impl_EndScene,
4328     IDirect3DDevice8Impl_Clear,
4329     IDirect3DDevice8Impl_SetTransform,
4330     IDirect3DDevice8Impl_GetTransform,
4331     IDirect3DDevice8Impl_MultiplyTransform,
4332     IDirect3DDevice8Impl_SetViewport,
4333     IDirect3DDevice8Impl_GetViewport,
4334     IDirect3DDevice8Impl_SetMaterial,
4335     IDirect3DDevice8Impl_GetMaterial,
4336     IDirect3DDevice8Impl_SetLight,
4337     IDirect3DDevice8Impl_GetLight,
4338     IDirect3DDevice8Impl_LightEnable,
4339     IDirect3DDevice8Impl_GetLightEnable,
4340     IDirect3DDevice8Impl_SetClipPlane,
4341     IDirect3DDevice8Impl_GetClipPlane,
4342     IDirect3DDevice8Impl_SetRenderState,
4343     IDirect3DDevice8Impl_GetRenderState,
4344     IDirect3DDevice8Impl_BeginStateBlock,
4345     IDirect3DDevice8Impl_EndStateBlock,
4346     IDirect3DDevice8Impl_ApplyStateBlock,
4347     IDirect3DDevice8Impl_CaptureStateBlock,
4348     IDirect3DDevice8Impl_DeleteStateBlock,
4349     IDirect3DDevice8Impl_CreateStateBlock,
4350     IDirect3DDevice8Impl_SetClipStatus,
4351     IDirect3DDevice8Impl_GetClipStatus,
4352     IDirect3DDevice8Impl_GetTexture,
4353     IDirect3DDevice8Impl_SetTexture,
4354     IDirect3DDevice8Impl_GetTextureStageState,
4355     IDirect3DDevice8Impl_SetTextureStageState,
4356     IDirect3DDevice8Impl_ValidateDevice,
4357     IDirect3DDevice8Impl_GetInfo,
4358     IDirect3DDevice8Impl_SetPaletteEntries,
4359     IDirect3DDevice8Impl_GetPaletteEntries,
4360     IDirect3DDevice8Impl_SetCurrentTexturePalette,
4361     IDirect3DDevice8Impl_GetCurrentTexturePalette,
4362     IDirect3DDevice8Impl_DrawPrimitive,
4363     IDirect3DDevice8Impl_DrawIndexedPrimitive,
4364     IDirect3DDevice8Impl_DrawPrimitiveUP,
4365     IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4366     IDirect3DDevice8Impl_ProcessVertices,
4367     IDirect3DDevice8Impl_CreateVertexShader,
4368     IDirect3DDevice8Impl_SetVertexShader,
4369     IDirect3DDevice8Impl_GetVertexShader,
4370     IDirect3DDevice8Impl_DeleteVertexShader,
4371     IDirect3DDevice8Impl_SetVertexShaderConstant,
4372     IDirect3DDevice8Impl_GetVertexShaderConstant,
4373     IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4374     IDirect3DDevice8Impl_GetVertexShaderFunction,
4375     IDirect3DDevice8Impl_SetStreamSource,
4376     IDirect3DDevice8Impl_GetStreamSource,
4377     IDirect3DDevice8Impl_SetIndices,
4378     IDirect3DDevice8Impl_GetIndices,
4379     IDirect3DDevice8Impl_CreatePixelShader,
4380     IDirect3DDevice8Impl_SetPixelShader,
4381     IDirect3DDevice8Impl_GetPixelShader,
4382     IDirect3DDevice8Impl_DeletePixelShader,
4383     IDirect3DDevice8Impl_SetPixelShaderConstant,
4384     IDirect3DDevice8Impl_GetPixelShaderConstant,
4385     IDirect3DDevice8Impl_GetPixelShaderFunction,
4386     IDirect3DDevice8Impl_DrawRectPatch,
4387     IDirect3DDevice8Impl_DrawTriPatch,
4388     IDirect3DDevice8Impl_DeletePatch
4389 };
4390
4391 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4392 {
4393 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4394   ICOM_THIS(IDirect3DDevice8Impl,iface);
4395
4396   ENTER_GL();
4397
4398 #if 0
4399   if (This->glCtx != This->render_ctx) {
4400     glXDestroyContext(This->display, This->render_ctx);
4401     This->render_ctx = This->glCtx;
4402   }
4403 #endif
4404   if (This->win != This->drawable) {
4405     glXDestroyPbuffer(This->display, This->drawable);
4406     This->drawable = This->win;
4407   }
4408
4409   LEAVE_GL();
4410
4411 #endif
4412   return D3D_OK;
4413 }
4414
4415 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4416                                                 IDirect3DSurface8* RenderSurface, 
4417                                                 IDirect3DSurface8* StencilSurface) {
4418
4419   HRESULT ret =  D3DERR_INVALIDCALL; 
4420   /**
4421    * Currently only active for GLX >= 1.3
4422    * for others versions we'll have to use GLXPixmaps
4423    *
4424    * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4425    * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4426    * so only check OpenGL version
4427    */
4428 #if defined(GL_VERSION_1_3) 
4429   GLXFBConfig* cfgs = NULL;
4430   int nCfgs = 0;
4431   int attribs[256];
4432   int nAttribs = 0;
4433   D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4434   D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4435   UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4436   UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4437   IDirect3DSurface8Impl* tmp;
4438
4439   ICOM_THIS(IDirect3DDevice8Impl,iface);
4440  
4441 #define PUSH1(att)        attribs[nAttribs++] = (att); 
4442 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4443
4444   PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4445   PUSH2(GLX_X_RENDERABLE,  TRUE);
4446   PUSH2(GLX_DOUBLEBUFFER, TRUE);
4447   
4448   switch (BackBufferFormat) {
4449     /* color buffer */
4450   case D3DFMT_P8:
4451     PUSH2(GLX_RENDER_TYPE,  GLX_COLOR_INDEX_BIT);
4452     PUSH2(GLX_BUFFER_SIZE,  8);
4453     PUSH2(GLX_DOUBLEBUFFER, TRUE);
4454     break;
4455     
4456   case D3DFMT_R3G3B2:
4457     PUSH2(GLX_RENDER_TYPE,  GLX_RGBA_BIT);
4458     PUSH2(GLX_RED_SIZE,     3);
4459     PUSH2(GLX_GREEN_SIZE,   3);
4460     PUSH2(GLX_BLUE_SIZE,    2);
4461     break;
4462     
4463   case D3DFMT_A1R5G5B5:
4464     PUSH2(GLX_ALPHA_SIZE,   1);
4465   case D3DFMT_X1R5G5B5:
4466     PUSH2(GLX_RED_SIZE,     5);
4467     PUSH2(GLX_GREEN_SIZE,   5);
4468     PUSH2(GLX_BLUE_SIZE,    5);
4469     break;
4470     
4471   case D3DFMT_R5G6B5:
4472     PUSH2(GLX_RED_SIZE,     5);
4473     PUSH2(GLX_GREEN_SIZE,   6);
4474     PUSH2(GLX_BLUE_SIZE,    5);
4475     break;
4476     
4477   case D3DFMT_A4R4G4B4:
4478     PUSH2(GLX_ALPHA_SIZE,   4);
4479   case D3DFMT_X4R4G4B4:
4480     PUSH2(GLX_RED_SIZE,     4);
4481     PUSH2(GLX_GREEN_SIZE,   4);
4482     PUSH2(GLX_BLUE_SIZE,    4);
4483     break;
4484     
4485   case D3DFMT_A8R8G8B8:
4486     PUSH2(GLX_ALPHA_SIZE,   8);
4487   case D3DFMT_R8G8B8:
4488   case D3DFMT_X8R8G8B8:
4489     PUSH2(GLX_RED_SIZE,     8);
4490     PUSH2(GLX_GREEN_SIZE,   8);
4491     PUSH2(GLX_BLUE_SIZE,    8);
4492     break;
4493
4494   default:
4495     break;
4496   }
4497    
4498   switch (StencilBufferFormat) { 
4499   case D3DFMT_D16_LOCKABLE:
4500   case D3DFMT_D16:
4501     PUSH2(GLX_DEPTH_SIZE,   16);
4502     break;
4503     
4504   case D3DFMT_D15S1:
4505     PUSH2(GLX_DEPTH_SIZE,   15);
4506     break;
4507     
4508   case D3DFMT_D24X8:
4509     PUSH2(GLX_DEPTH_SIZE,   24);
4510     break;
4511     
4512   case D3DFMT_D24X4S4:
4513     PUSH2(GLX_DEPTH_SIZE,   24);
4514     PUSH2(GLX_STENCIL_SIZE, 4);
4515     break;
4516     
4517   case D3DFMT_D24S8:
4518     PUSH2(GLX_DEPTH_SIZE,   24);
4519     PUSH2(GLX_STENCIL_SIZE, 8);
4520     break;
4521     
4522   case D3DFMT_D32:
4523     PUSH2(GLX_DEPTH_SIZE,   32);
4524     break;
4525
4526   default:
4527     break;
4528   }
4529
4530   PUSH1(None);
4531   
4532   ENTER_GL();
4533
4534   cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4535   if (NULL != cfgs) {
4536 #ifdef EXTRA_TRACES
4537     int i;
4538     for (i = 0; i < nCfgs; ++i) {
4539       TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4540     }
4541 #endif
4542
4543     if (NULL != This->renderTarget) {
4544       /*GLenum prev_read; */
4545       glFlush();
4546       vcheckGLcall("glFlush");
4547
4548 #ifdef EXTRA_TRACES
4549       /** very very usefull debug code */
4550       glXSwapBuffers(This->display, This->drawable);   
4551       printf("Hit Enter to get next frame ...\n");
4552       getchar();
4553 #endif
4554
4555 #if 0
4556       glGetIntegerv(GL_READ_BUFFER, &prev_read);
4557       vcheckGLcall("glIntegerv");
4558       glReadBuffer(GL_BACK);
4559       vcheckGLcall("glReadBuffer");
4560       {
4561         long j;
4562         long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4563
4564         if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4565             pitch = pitch / 2;
4566
4567         for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4568           glReadPixels(0, 
4569                        This->renderTarget->myDesc.Height - j - 1, 
4570                        This->renderTarget->myDesc.Width, 
4571                        1,
4572                        D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format), 
4573                        D3DFmt2GLType(This, This->renderTarget->myDesc.Format), 
4574                        This->renderTarget->allocatedMemory + j * pitch);
4575           vcheckGLcall("glReadPixels");
4576         }
4577       }      
4578       glReadBuffer(prev_read);
4579       vcheckGLcall("glReadBuffer");
4580 #endif
4581     }
4582
4583     if (BackBufferFormat != This->renderTarget->myDesc.Format && 
4584         StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4585       nAttribs = 0;
4586       PUSH2(GLX_PBUFFER_WIDTH,  Width);
4587       PUSH2(GLX_PBUFFER_HEIGHT, Height);
4588       PUSH1(None);
4589       This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4590             
4591       This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4592       if (NULL == This->render_ctx) {
4593         ERR("cannot create glxContext\n"); 
4594       }
4595
4596       glFlush();
4597       glXSwapBuffers(This->display, This->drawable);
4598       if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4599         TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4600       }
4601       checkGLcall("glXMakeContextCurrent");
4602     }
4603
4604     tmp = This->renderTarget;
4605     This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4606     IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4607     IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4608
4609     tmp = This->stencilBufferTarget;
4610     This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4611     if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4612     if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4613
4614     {
4615       DWORD value;
4616       /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4617       This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4618       /* Force updating the cull mode */
4619       IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4620       IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4621       /* Force updating projection matrix */
4622       This->last_was_rhw = FALSE;
4623       This->proj_valid = FALSE;
4624     }
4625
4626     ret = D3D_OK;
4627
4628   } else {
4629     ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4630   }
4631
4632 #undef PUSH1
4633 #undef PUSH2
4634
4635   LEAVE_GL();
4636
4637 #endif
4638
4639   return ret;
4640 }