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