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