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