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