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