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