Fix format string in WSAAddressToStringA().
[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(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     TRACE("(%p) : stub\n", This);
1291     return D3D_OK;
1292 }
1293
1294 HRESULT  WINAPI  IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1295     IDirect3DBaseTexture8* cont = NULL;
1296     HRESULT hr;
1297     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1298     TRACE("(%p)\n", This);
1299
1300     ENTER_GL();
1301
1302     glFlush();
1303     checkGLcall("glFlush");
1304
1305 #if 0 /* Useful for debugging sometimes! */
1306     printf("Hit Enter ...\n");
1307     getchar();
1308 #endif
1309
1310     if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
1311 #if 0
1312         GLenum prev_read;
1313         glGetIntegerv(GL_READ_BUFFER, &prev_read);
1314         vcheckGLcall("glIntegerv");
1315         glReadBuffer(GL_FRONT);
1316         vcheckGLcall("glReadBuffer");
1317         {
1318           long j;
1319           long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1320
1321           if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1322               pitch = pitch / 2;
1323
1324           for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1325             glReadPixels(0, 
1326                          This->renderTarget->myDesc.Height - j - 1, 
1327                          This->renderTarget->myDesc.Width, 
1328                          1,
1329                          D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format), 
1330                          D3DFmt2GLType(This, This->renderTarget->myDesc.Format), 
1331                          This->renderTarget->allocatedMemory + j * pitch);
1332             vcheckGLcall("glReadPixels");
1333           }
1334         }      
1335         glReadBuffer(prev_read);
1336         vcheckGLcall("glReadBuffer");
1337 #endif
1338
1339       hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1340       if (SUCCEEDED(hr) && NULL != cont) {
1341         /** always dirtify for now. we must find a better way to see that surface have been modified */
1342         This->renderTarget->inPBuffer = TRUE;
1343         This->renderTarget->inTexture = FALSE;
1344         IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1345         IDirect3DBaseTexture8_PreLoad(cont);
1346         This->renderTarget->inPBuffer = FALSE;
1347         IDirect3DBaseTexture8Impl_Release(cont);
1348         cont = NULL;
1349       }
1350     }
1351
1352     LEAVE_GL();
1353     return D3D_OK;
1354 }
1355 HRESULT  WINAPI  IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1356     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1357
1358     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1359       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1360       when the depth-buffer format does not contain stencil buffer information, this method fails. */
1361     GLbitfield glMask = 0;
1362     GLboolean old_ztest;
1363     GLfloat old_z_clear_value;
1364     GLint   old_stencil_clear_value;
1365     GLfloat old_color_clear_value[4];
1366     unsigned int i;
1367     CONST D3DRECT* curRect;
1368
1369     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1370           Count, pRects, Flags, Z, Stencil);
1371
1372     ENTER_GL();
1373     glEnable(GL_SCISSOR_TEST);
1374     checkGLcall("glEnable GL_SCISSOR_TEST");
1375     if (Count > 0 && pRects) {
1376         curRect = pRects;
1377     } else {
1378         curRect = NULL;
1379     }
1380
1381     /* Only set the values up once, as they are not changing */
1382     if (Flags & D3DCLEAR_STENCIL) {     
1383         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1384         glClearStencil(Stencil);
1385         checkGLcall("glClearStencil");
1386         glMask = glMask | GL_STENCIL_BUFFER_BIT;
1387         glStencilMask(0xFFFFFFFF);
1388     }
1389
1390     if (Flags & D3DCLEAR_ZBUFFER) {
1391         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1392         glDepthMask(GL_TRUE); 
1393         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1394         glClearDepth(Z);
1395         checkGLcall("glClearDepth");
1396         glMask = glMask | GL_DEPTH_BUFFER_BIT;
1397     }
1398
1399     if (Flags & D3DCLEAR_TARGET) {
1400         TRACE("Clearing screen with glClear to color %lx\n", Color);
1401         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1402         glClearColor(((Color >> 16) & 0xFF) / 255.0f, 
1403                      ((Color >>  8) & 0xFF) / 255.0f,
1404                      ((Color >>  0) & 0xFF) / 255.0f, 
1405                      ((Color >> 24) & 0xFF) / 255.0f);
1406         checkGLcall("glClearColor");
1407
1408         /* Clear ALL colors! */
1409         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1410         glMask = glMask | GL_COLOR_BUFFER_BIT;
1411     }
1412
1413     /* Now process each rect in turn */
1414     for (i = 0; i < Count || i == 0; i++) {
1415
1416         if (curRect) {
1417             /* Note gl uses lower left, width/height */
1418             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1419                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1420                   curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2), 
1421                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1422             glScissor(curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2), 
1423                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1424             checkGLcall("glScissor");
1425         } else {
1426             glScissor(This->StateBlock->viewport.X, 
1427                       (This->renderTarget->myDesc.Height - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)), 
1428                       This->StateBlock->viewport.Width, 
1429                       This->StateBlock->viewport.Height);
1430             checkGLcall("glScissor");
1431         }
1432
1433         /* Clear the selected rectangle (or full screen) */
1434         glClear(glMask);
1435         checkGLcall("glClear");
1436
1437         /* Step to the next rectangle */
1438         if (curRect) curRect = curRect + sizeof(D3DRECT);
1439     }
1440
1441     /* Restore the old values (why..?) */
1442     if (Flags & D3DCLEAR_STENCIL) {
1443         glClearStencil(old_stencil_clear_value);
1444         glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1445     }    
1446     if (Flags & D3DCLEAR_ZBUFFER) {
1447         glDepthMask(old_ztest);
1448         glClearDepth(old_z_clear_value);
1449     }
1450     if (Flags & D3DCLEAR_TARGET) {
1451         glClearColor(old_color_clear_value[0], 
1452                      old_color_clear_value[1],
1453                      old_color_clear_value[2], 
1454                      old_color_clear_value[3]);
1455         glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE, 
1456                     This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1457                     This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE, 
1458                     This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1459     }
1460
1461     glDisable(GL_SCISSOR_TEST);
1462     checkGLcall("glDisable");
1463     LEAVE_GL();
1464
1465     return D3D_OK;
1466 }
1467 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1468     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1469     unsigned int k;
1470
1471     /* Most of this routine, comments included copied from ddraw tree initially: */
1472     TRACE("(%p) : State=%d\n", This, d3dts);
1473
1474     /* Handle recording of state blocks */
1475     if (This->isRecordingState) {
1476         TRACE("Recording... not performing anything\n");
1477         This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1478         This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1479         memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1480         return D3D_OK;
1481     }
1482
1483     /*
1484      * if the new matrix is the same as the current one,
1485      * we cut off any further processing. this seems to be a reasonable
1486      * optimization because as was noticed, some apps (warcraft3 for example)
1487      * tend towards setting the same matrix repeatedly for some dumb reason.
1488      *
1489      * From here on we assume that the new matrix is different, wherever it matters
1490      * but note
1491      */
1492     if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1493         TRACE("The app is setting the same matrix over again\n");
1494         return D3D_OK;
1495     } else {
1496         conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1497     }
1498
1499     /*
1500        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1501        where ViewMat = Camera space, WorldMat = world space.
1502
1503        In OpenGL, camera and world space is combined into GL_MODELVIEW
1504        matrix.  The Projection matrix stay projection matrix. 
1505      */
1506
1507     /* Capture the times we can just ignore the change */
1508     if (d3dts == D3DTS_WORLDMATRIX(0)) {
1509         This->modelview_valid = FALSE;
1510         return D3D_OK;
1511
1512     } else if (d3dts == D3DTS_PROJECTION) {
1513         This->proj_valid = FALSE;
1514         return D3D_OK;
1515
1516     } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511  */
1517         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1518         FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1519         return D3D_OK;
1520     } 
1521     
1522     /* Chances are we really are going to have to change a matrix */
1523     ENTER_GL();
1524
1525     if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1526         if (d3dts < GL_LIMITS(textures)) {
1527             int tex = d3dts - D3DTS_TEXTURE0;
1528 #if defined(GL_VERSION_1_3)
1529             glActiveTexture(GL_TEXTURE0 + tex);
1530             checkGLcall("glActiveTexture");
1531 #else 
1532             glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1533             checkGLcall("glActiveTextureARB");
1534 #endif
1535             set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1536         }
1537
1538     } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1539
1540         PLIGHTINFOEL *lightChain = NULL;
1541         float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1542         This->modelview_valid = FALSE;
1543         This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1544         glMatrixMode(GL_MODELVIEW);
1545         checkGLcall("glMatrixMode(GL_MODELVIEW)");
1546         glPushMatrix();
1547         glLoadMatrixf((float *)lpmatrix);
1548         checkGLcall("glLoadMatrixf(...)");
1549
1550         /* If we are changing the View matrix, reset the light and clipping planes to the new view   
1551          * NOTE: We have to reset the positions even if the light/plane is not currently
1552          *       enabled, since the call to enable it will not reset the position.                 
1553          * NOTE2: Apparently texture transforms do NOT need reapplying
1554          */
1555
1556         /* Reset lights */
1557         lightChain = This->StateBlock->lights;
1558         while (lightChain && lightChain->glIndex != -1) {
1559             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1560             checkGLcall("glLightfv posn");
1561             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1562             checkGLcall("glLightfv dirn");
1563             lightChain = lightChain->next;
1564         }
1565         /* Reset Clipping Planes if clipping is enabled */
1566         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1567             glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1568             checkGLcall("glClipPlane");
1569         }
1570         glPopMatrix();
1571
1572     } else { /* What was requested!?? */
1573         WARN("invalid matrix specified: %i\n", d3dts);
1574
1575     }
1576
1577     /* Release lock, all done */
1578     LEAVE_GL();
1579     return D3D_OK;
1580
1581 }
1582 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1583     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1584     TRACE("(%p) : for State %d\n", This, State);
1585     memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1586     return D3D_OK;
1587 }
1588
1589 HRESULT  WINAPI  IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1590     D3DMATRIX *mat = NULL;
1591     D3DMATRIX temp;
1592
1593     /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1594         but works regardless of recording being on. 
1595         If this is found to be wrong, change to StateBlock.                             */
1596     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1597     TRACE("(%p) : For state %u\n", This, State);
1598
1599     if (State < HIGHEST_TRANSFORMSTATE)
1600     {
1601         mat = &This->UpdateStateBlock->transforms[State];
1602     } else {
1603         FIXME("Unhandled transform state!!\n");
1604     }
1605
1606     /* Copied from ddraw code:  */
1607     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);
1608     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);
1609     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);
1610     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);
1611
1612     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);
1613     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);
1614     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);
1615     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);
1616
1617     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);
1618     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);
1619     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);
1620     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);
1621
1622     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);
1623     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);
1624     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);
1625     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);
1626
1627     /* Apply change via set transform - will reapply to eg. lights this way */
1628     IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1629     return D3D_OK;
1630 }
1631 HRESULT  WINAPI  IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1632     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1633
1634     TRACE("(%p)\n", This);
1635     This->UpdateStateBlock->Changed.viewport = TRUE;
1636     This->UpdateStateBlock->Set.viewport = TRUE;
1637     memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1638
1639     /* Handle recording of state blocks */
1640     if (This->isRecordingState) {
1641         TRACE("Recording... not performing anything\n");
1642         return D3D_OK;
1643     }
1644
1645     ENTER_GL();
1646
1647     TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1648           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1649
1650     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1651     checkGLcall("glDepthRange");
1652     /* Note: GL requires lower left, DirectX supplies upper left */
1653     glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)), 
1654                pViewport->Width, pViewport->Height);
1655     checkGLcall("glViewport");
1656
1657     LEAVE_GL();
1658
1659     return D3D_OK;
1660
1661 }
1662 HRESULT  WINAPI  IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1663     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1664     TRACE("(%p)\n", This);
1665     memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1666     return D3D_OK;
1667 }
1668
1669 HRESULT  WINAPI  IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1670     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1671
1672     This->UpdateStateBlock->Changed.material = TRUE;
1673     This->UpdateStateBlock->Set.material = TRUE;
1674     memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1675
1676     /* Handle recording of state blocks */
1677     if (This->isRecordingState) {
1678         TRACE("Recording... not performing anything\n");
1679         return D3D_OK;
1680     }
1681
1682     ENTER_GL();
1683     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1684     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1685     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1686     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1687     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1688
1689     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1690     checkGLcall("glMaterialfv");
1691     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1692     checkGLcall("glMaterialfv");
1693
1694     /* Only change material color if specular is enabled, otherwise it is set to black */
1695     if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1696        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1697        checkGLcall("glMaterialfv");
1698     } else {
1699        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1700        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1701        checkGLcall("glMaterialfv");
1702     }
1703     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1704     checkGLcall("glMaterialfv");
1705     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1706     checkGLcall("glMaterialf");
1707
1708     LEAVE_GL();
1709     return D3D_OK;
1710 }
1711 HRESULT  WINAPI  IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1712     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1713     memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1714     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1715     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1716     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1717     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1718     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1719     return D3D_OK;
1720 }
1721
1722 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1723    you can reference any indexes you want as long as that number max are enabled are any
1724    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1725    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1726    but when recording, just build a chain pretty much of commands to be replayed.                  */
1727    
1728 HRESULT  WINAPI  IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1729     float rho;
1730     PLIGHTINFOEL *object, *temp;
1731
1732     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1733     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1734
1735     /* If recording state block, just add to end of lights chain */
1736     if (This->isRecordingState) {
1737         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1738         if (NULL == object) {
1739             return D3DERR_OUTOFVIDEOMEMORY;
1740         }
1741         memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1742         object->OriginalIndex = Index;
1743         object->glIndex = -1;
1744         object->changed = TRUE;
1745
1746         /* Add to the END of the chain of lights changes to be replayed */
1747         if (This->UpdateStateBlock->lights == NULL) {
1748             This->UpdateStateBlock->lights = object;
1749         } else {
1750             temp = This->UpdateStateBlock->lights;
1751             while (temp->next != NULL) temp=temp->next;
1752             temp->next = object;
1753         }
1754         TRACE("Recording... not performing anything more\n");
1755         return D3D_OK;
1756     }
1757
1758     /* Ok, not recording any longer so do real work */
1759     object = This->StateBlock->lights;
1760     while (object != NULL && object->OriginalIndex != Index) object = object->next;
1761
1762     /* If we didn't find it in the list of lights, time to add it */
1763     if (object == NULL) {
1764         PLIGHTINFOEL *insertAt,*prevPos;
1765
1766         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1767         if (NULL == object) {
1768             return D3DERR_OUTOFVIDEOMEMORY;
1769         }
1770         object->OriginalIndex = Index;
1771         object->glIndex = -1;
1772
1773         /* Add it to the front of list with the idea that lights will be changed as needed 
1774            BUT after any lights currently assigned GL indexes                             */
1775         insertAt = This->StateBlock->lights;
1776         prevPos  = NULL;
1777         while (insertAt != NULL && insertAt->glIndex != -1) {
1778             prevPos  = insertAt;
1779             insertAt = insertAt->next;
1780         }
1781
1782         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1783             This->StateBlock->lights = object;
1784         } else if (insertAt == NULL) { /* End of list */
1785             prevPos->next = object;
1786             object->prev = prevPos;
1787         } else { /* Middle of chain */
1788             if (prevPos == NULL) {
1789                 This->StateBlock->lights = object;
1790             } else {
1791                 prevPos->next = object;
1792             }
1793             object->prev = prevPos;
1794             object->next = insertAt;
1795             insertAt->prev = object;
1796         }
1797     }
1798
1799     /* Initialze the object */
1800     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,
1801           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1802           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1803           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1804     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1805           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1806     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1807
1808     /* Save away the information */
1809     memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1810
1811     switch (pLight->Type) {
1812     case D3DLIGHT_POINT:
1813         /* Position */
1814         object->lightPosn[0] = pLight->Position.x;
1815         object->lightPosn[1] = pLight->Position.y;
1816         object->lightPosn[2] = pLight->Position.z;
1817         object->lightPosn[3] = 1.0f;
1818         object->cutoff = 180.0f;
1819         /* FIXME: Range */
1820         break;
1821
1822     case D3DLIGHT_DIRECTIONAL:
1823         /* Direction */
1824         object->lightPosn[0] = -pLight->Direction.x;
1825         object->lightPosn[1] = -pLight->Direction.y;
1826         object->lightPosn[2] = -pLight->Direction.z;
1827         object->lightPosn[3] = 0.0;
1828         object->exponent     = 0.0f;
1829         object->cutoff       = 180.0f;
1830         break;
1831
1832     case D3DLIGHT_SPOT:
1833         /* Position */
1834         object->lightPosn[0] = pLight->Position.x;
1835         object->lightPosn[1] = pLight->Position.y;
1836         object->lightPosn[2] = pLight->Position.z;
1837         object->lightPosn[3] = 1.0;
1838
1839         /* Direction */
1840         object->lightDirn[0] = pLight->Direction.x;
1841         object->lightDirn[1] = pLight->Direction.y;
1842         object->lightDirn[2] = pLight->Direction.z;
1843         object->lightDirn[3] = 1.0;
1844
1845         /*
1846          * opengl-ish and d3d-ish spot lights use too different models for the
1847          * light "intensity" as a function of the angle towards the main light direction,
1848          * so we only can approximate very roughly.
1849          * however spot lights are rather rarely used in games (if ever used at all).
1850          * furthermore if still used, probably nobody pays attention to such details.
1851          */
1852         if (pLight->Falloff == 0) {
1853             rho = 6.28f;
1854         } else {
1855             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1856         }
1857         if (rho < 0.0001) rho = 0.0001f;
1858         object->exponent = -0.3/log(cos(rho/2));
1859         object->cutoff = pLight->Phi*90/M_PI;
1860
1861         /* FIXME: Range */
1862         break;
1863
1864     default:
1865         FIXME("Unrecognized light type %d\n", pLight->Type);
1866     }
1867
1868     /* Update the live definitions if the light is currently assigned a glIndex */
1869     if (object->glIndex != -1) {
1870         setup_light(iface, object->glIndex, object);
1871     }
1872     return D3D_OK;
1873 }
1874 HRESULT  WINAPI  IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1875     PLIGHTINFOEL *lightInfo = NULL;
1876     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; 
1877     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1878     
1879     /* Locate the light in the live lights */
1880     lightInfo = This->StateBlock->lights;
1881     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1882
1883     if (lightInfo == NULL) {
1884         TRACE("Light information requested but light not defined\n");
1885         return D3DERR_INVALIDCALL;
1886     }
1887
1888     memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1889     return D3D_OK;
1890 }
1891 HRESULT  WINAPI  IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1892     PLIGHTINFOEL *lightInfo = NULL;
1893     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1894     TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1895
1896     /* If recording state block, just add to end of lights chain with changedEnable set to true */
1897     if (This->isRecordingState) {
1898         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1899         if (NULL == lightInfo) {
1900             return D3DERR_OUTOFVIDEOMEMORY;
1901         }
1902         lightInfo->OriginalIndex = Index;
1903         lightInfo->glIndex = -1;
1904         lightInfo->enabledChanged = TRUE;
1905
1906         /* Add to the END of the chain of lights changes to be replayed */
1907         if (This->UpdateStateBlock->lights == NULL) {
1908             This->UpdateStateBlock->lights = lightInfo;
1909         } else {
1910             PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1911             while (temp->next != NULL) temp=temp->next;
1912             temp->next = lightInfo;
1913         }
1914         TRACE("Recording... not performing anything more\n");
1915         return D3D_OK;
1916     }
1917
1918     /* Not recording... So, locate the light in the live lights */
1919     lightInfo = This->StateBlock->lights;
1920     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1921
1922     /* Special case - enabling an undefined light creates one with a strict set of parms! */
1923     if (lightInfo == NULL) {
1924         D3DLIGHT8 lightParms;
1925         /* Warning - untested code :-) Prob safe to change fixme to a trace but
1926              wait until someone confirms it seems to work!                     */
1927         TRACE("Light enabled requested but light not defined, so defining one!\n"); 
1928         lightParms.Type = D3DLIGHT_DIRECTIONAL;
1929         lightParms.Diffuse.r = 1.0;
1930         lightParms.Diffuse.g = 1.0;
1931         lightParms.Diffuse.b = 1.0;
1932         lightParms.Diffuse.a = 0.0;
1933         lightParms.Specular.r = 0.0;
1934         lightParms.Specular.g = 0.0;
1935         lightParms.Specular.b = 0.0;
1936         lightParms.Specular.a = 0.0;
1937         lightParms.Ambient.r = 0.0;
1938         lightParms.Ambient.g = 0.0;
1939         lightParms.Ambient.b = 0.0;
1940         lightParms.Ambient.a = 0.0;
1941         lightParms.Position.x = 0.0;
1942         lightParms.Position.y = 0.0;
1943         lightParms.Position.z = 0.0;
1944         lightParms.Direction.x = 0.0;
1945         lightParms.Direction.y = 0.0;
1946         lightParms.Direction.z = 1.0;
1947         lightParms.Range = 0.0;
1948         lightParms.Falloff = 0.0;
1949         lightParms.Attenuation0 = 0.0;
1950         lightParms.Attenuation1 = 0.0;
1951         lightParms.Attenuation2 = 0.0;
1952         lightParms.Theta = 0.0;
1953         lightParms.Phi = 0.0;
1954         IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1955
1956         /* Search for it again! Should be fairly quick as near head of list */
1957         lightInfo = This->StateBlock->lights;
1958         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1959         if (lightInfo == NULL) {
1960             FIXME("Adding default lights has failed dismally\n");
1961             return D3DERR_INVALIDCALL;
1962         }
1963     }
1964
1965     /* OK, we now have a light... */
1966     if (Enable == FALSE) {
1967
1968         /* If we are disabling it, check it was enabled, and
1969            still only do something if it has assigned a glIndex (which it should have!)   */
1970         if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1971             TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1972             ENTER_GL();
1973             glDisable(GL_LIGHT0 + lightInfo->glIndex);
1974             checkGLcall("glDisable GL_LIGHT0+Index");
1975             LEAVE_GL();
1976         } else {
1977             TRACE("Nothing to do as light was not enabled\n");
1978         }
1979         lightInfo->lightEnabled = FALSE;
1980     } else {
1981
1982         /* We are enabling it. If it is enabled, its really simple */
1983         if (lightInfo->lightEnabled == TRUE) {
1984             /* nop */
1985             TRACE("Nothing to do as light was enabled\n");
1986
1987         /* If it already has a glIndex, its still simple */
1988         } else if (lightInfo->glIndex != -1) {
1989             TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1990             lightInfo->lightEnabled = TRUE;
1991             ENTER_GL();
1992             glEnable(GL_LIGHT0 + lightInfo->glIndex);
1993             checkGLcall("glEnable GL_LIGHT0+Index already setup");
1994             LEAVE_GL();
1995
1996         /* Otherwise got to find space - lights are ordered gl indexes first */
1997         } else {
1998             PLIGHTINFOEL *bsf  = NULL;
1999             PLIGHTINFOEL *pos  = This->StateBlock->lights;
2000             PLIGHTINFOEL *prev = NULL;
2001             int           Index= 0;
2002             int           glIndex = -1;
2003
2004             /* Try to minimize changes as much as possible */
2005             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2006
2007                 /* Try to remember which index can be replaced if necessary */
2008                 if (bsf==NULL && pos->lightEnabled == FALSE) {
2009                     /* Found a light we can replace, save as best replacement */
2010                     bsf = pos;
2011                 }
2012
2013                 /* Step to next space */
2014                 prev = pos;
2015                 pos = pos->next;
2016                 Index ++;
2017             }
2018
2019             /* If we have too many active lights, fail the call */
2020             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2021                 FIXME("Program requests too many concurrent lights\n");
2022                 return D3DERR_INVALIDCALL;
2023
2024             /* If we have allocated all lights, but not all are enabled,
2025                reuse one which is not enabled                           */
2026             } else if (Index == This->maxConcurrentLights) {
2027                 /* use bsf - Simply swap the new light and the BSF one */
2028                 PLIGHTINFOEL *bsfNext = bsf->next;
2029                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2030
2031                 /* Sort out ends */
2032                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2033                 if (bsf->prev != NULL) {
2034                     bsf->prev->next = lightInfo;
2035                 } else {
2036                     This->StateBlock->lights = lightInfo;
2037                 }
2038
2039                 /* If not side by side, lots of chains to update */
2040                 if (bsf->next != lightInfo) {
2041                     lightInfo->prev->next = bsf;
2042                     bsf->next->prev = lightInfo;
2043                     bsf->next       = lightInfo->next;
2044                     bsf->prev       = lightInfo->prev;
2045                     lightInfo->next = bsfNext;
2046                     lightInfo->prev = bsfPrev;
2047
2048                 } else {
2049                     /* Simple swaps */
2050                     bsf->prev = lightInfo;
2051                     bsf->next = lightInfo->next;
2052                     lightInfo->next = bsf;
2053                     lightInfo->prev = bsfPrev;
2054                 }
2055
2056
2057                 /* Update states */
2058                 glIndex = bsf->glIndex;
2059                 bsf->glIndex = -1;
2060                 lightInfo->glIndex = glIndex;
2061                 lightInfo->lightEnabled = TRUE;
2062
2063                 /* Finally set up the light in gl itself */
2064                 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2065                 ENTER_GL();
2066                 setup_light(iface, glIndex, lightInfo);
2067                 glEnable(GL_LIGHT0 + glIndex);
2068                 checkGLcall("glEnable GL_LIGHT0 new setup");
2069                 LEAVE_GL();
2070
2071             /* If we reached the end of the allocated lights, with space in the
2072                gl lights, setup a new light                                     */
2073             } else if (pos->glIndex == -1) {
2074
2075                 /* We reached the end of the allocated gl lights, so already 
2076                     know the index of the next one!                          */
2077                 glIndex = Index;
2078                 lightInfo->glIndex = glIndex;
2079                 lightInfo->lightEnabled = TRUE;
2080
2081                 /* In an ideal world, its already in the right place */
2082                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2083                    /* No need to move it */
2084                 } else {
2085                     /* Remove this light from the list */
2086                     lightInfo->prev->next = lightInfo->next;
2087                     if (lightInfo->next != NULL) {
2088                         lightInfo->next->prev = lightInfo->prev;
2089                     }
2090
2091                     /* Add in at appropriate place (inbetween prev and pos) */
2092                     lightInfo->prev = prev;
2093                     lightInfo->next = pos;
2094                     if (prev == NULL) {
2095                         This->StateBlock->lights = lightInfo;
2096                     } else {
2097                         prev->next = lightInfo;
2098                     }
2099                     if (pos != NULL) {
2100                         pos->prev = lightInfo;
2101                     }
2102                 }
2103
2104                 /* Finally set up the light in gl itself */
2105                 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2106                 ENTER_GL();
2107                 setup_light(iface, glIndex, lightInfo);
2108                 glEnable(GL_LIGHT0 + glIndex);
2109                 checkGLcall("glEnable GL_LIGHT0 new setup");
2110                 LEAVE_GL();
2111                 
2112             }
2113         }
2114     }
2115     return D3D_OK;
2116 }
2117 HRESULT  WINAPI  IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2118
2119     PLIGHTINFOEL *lightInfo = NULL;
2120     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; 
2121     TRACE("(%p) : for idx(%ld)\n", This, Index);
2122     
2123     /* Locate the light in the live lights */
2124     lightInfo = This->StateBlock->lights;
2125     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2126
2127     if (lightInfo == NULL) {
2128         TRACE("Light enabled state requested but light not defined\n");
2129         return D3DERR_INVALIDCALL;
2130     }
2131     *pEnable = lightInfo->lightEnabled;
2132     return D3D_OK;
2133 }
2134 HRESULT  WINAPI  IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2135     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2136     TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2137
2138     /* Validate Index */
2139     if (Index >= GL_LIMITS(clipplanes)) {
2140         TRACE("Application has requested clipplane this device doesn't support\n");
2141         return D3DERR_INVALIDCALL;
2142     }
2143
2144     This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2145     This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2146     This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2147     This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2148     This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2149     This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2150
2151     /* Handle recording of state blocks */
2152     if (This->isRecordingState) {
2153         TRACE("Recording... not performing anything\n");
2154         return D3D_OK;
2155     }
2156
2157     /* Apply it */
2158
2159     ENTER_GL();
2160
2161     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2162     glMatrixMode(GL_MODELVIEW);
2163     glPushMatrix();
2164     glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2165
2166     TRACE("Clipplane [%f,%f,%f,%f]\n", 
2167           This->UpdateStateBlock->clipplane[Index][0], 
2168           This->UpdateStateBlock->clipplane[Index][1],
2169           This->UpdateStateBlock->clipplane[Index][2], 
2170           This->UpdateStateBlock->clipplane[Index][3]);
2171     glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2172     checkGLcall("glClipPlane");
2173
2174     glPopMatrix();
2175
2176     LEAVE_GL();
2177
2178     return D3D_OK;
2179 }
2180 HRESULT  WINAPI  IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2181     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2182     TRACE("(%p) : for idx %ld\n", This, Index);
2183
2184     /* Validate Index */
2185     if (Index >= GL_LIMITS(clipplanes)) {
2186         TRACE("Application has requested clipplane this device doesn't support\n");
2187         return D3DERR_INVALIDCALL;
2188     }
2189
2190     pPlane[0] = This->StateBlock->clipplane[Index][0];
2191     pPlane[1] = This->StateBlock->clipplane[Index][1];
2192     pPlane[2] = This->StateBlock->clipplane[Index][2];
2193     pPlane[3] = This->StateBlock->clipplane[Index][3];
2194     return D3D_OK;
2195 }
2196 HRESULT  WINAPI  IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2197     union {
2198         DWORD d;
2199         float f;
2200     } tmpvalue;
2201     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2202     DWORD OldValue = This->StateBlock->renderstate[State];
2203         
2204     TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2205     This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2206     This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2207     This->UpdateStateBlock->renderstate[State] = Value;
2208
2209     /* Handle recording of state blocks */
2210     if (This->isRecordingState) {
2211         TRACE("Recording... not performing anything\n");
2212         return D3D_OK;
2213     }
2214
2215     ENTER_GL();
2216
2217     switch (State) {
2218     case D3DRS_FILLMODE                  :
2219         switch ((D3DFILLMODE) Value) {
2220         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2221         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2222         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2223         default:
2224             FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2225         }
2226         checkGLcall("glPolygonMode (fillmode)");
2227         break;
2228
2229     case D3DRS_LIGHTING                  :
2230         if (Value) {
2231             glEnable(GL_LIGHTING);
2232             checkGLcall("glEnable GL_LIGHTING");
2233         } else {
2234             glDisable(GL_LIGHTING);
2235             checkGLcall("glDisable GL_LIGHTING");
2236         }
2237         break;
2238
2239     case D3DRS_ZENABLE                   :
2240         switch ((D3DZBUFFERTYPE) Value) {
2241         case D3DZB_FALSE:
2242             glDisable(GL_DEPTH_TEST);
2243             checkGLcall("glDisable GL_DEPTH_TEST");
2244             break;
2245         case D3DZB_TRUE:
2246             glEnable(GL_DEPTH_TEST);
2247             checkGLcall("glEnable GL_DEPTH_TEST");
2248             break;
2249         case D3DZB_USEW:
2250             glEnable(GL_DEPTH_TEST);
2251             checkGLcall("glEnable GL_DEPTH_TEST");
2252             FIXME("W buffer is not well handled\n");
2253             break;
2254         default:
2255             FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2256         }
2257         break;
2258
2259     case D3DRS_CULLMODE                  :
2260
2261         /* If we are culling "back faces with clockwise vertices" then
2262            set front faces to be counter clockwise and enable culling  
2263            of back faces                                               */
2264         switch ((D3DCULL) Value) {
2265         case D3DCULL_NONE:
2266             glDisable(GL_CULL_FACE);
2267             checkGLcall("glDisable GL_CULL_FACE");
2268             break;
2269         case D3DCULL_CW:
2270             glEnable(GL_CULL_FACE);
2271             checkGLcall("glEnable GL_CULL_FACE");
2272             if (This->renderUpsideDown) {
2273                 glFrontFace(GL_CW);
2274                 checkGLcall("glFrontFace GL_CW");
2275             } else {
2276                 glFrontFace(GL_CCW);
2277                 checkGLcall("glFrontFace GL_CCW");
2278             }
2279             glCullFace(GL_BACK);
2280             break;
2281         case D3DCULL_CCW:
2282             glEnable(GL_CULL_FACE);
2283             checkGLcall("glEnable GL_CULL_FACE");
2284             if (This->renderUpsideDown) {
2285                 glFrontFace(GL_CCW); 
2286                 checkGLcall("glFrontFace GL_CCW");
2287             } else {
2288                 glFrontFace(GL_CW);
2289                 checkGLcall("glFrontFace GL_CW");
2290             }
2291             glCullFace(GL_BACK);
2292             break;
2293         default:
2294             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2295         }
2296         break;
2297
2298     case D3DRS_SHADEMODE                 :
2299         switch ((D3DSHADEMODE) Value) {
2300         case D3DSHADE_FLAT:
2301             glShadeModel(GL_FLAT);
2302             checkGLcall("glShadeModel");
2303             break;
2304         case D3DSHADE_GOURAUD:
2305             glShadeModel(GL_SMOOTH);
2306             checkGLcall("glShadeModel");
2307             break;
2308         case D3DSHADE_PHONG:
2309             FIXME("D3DSHADE_PHONG isn't supported?\n");
2310
2311             LEAVE_GL();
2312             return D3DERR_INVALIDCALL;
2313         default:
2314             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2315         }
2316         break;
2317
2318     case D3DRS_DITHERENABLE              :
2319         if (Value) {
2320             glEnable(GL_DITHER);
2321             checkGLcall("glEnable GL_DITHER");
2322         } else {
2323             glDisable(GL_DITHER);
2324             checkGLcall("glDisable GL_DITHER");
2325         }
2326         break;
2327
2328     case D3DRS_ZWRITEENABLE              :
2329         if (Value) {
2330             glDepthMask(1);
2331             checkGLcall("glDepthMask");
2332         } else {
2333             glDepthMask(0);
2334             checkGLcall("glDepthMask");
2335         }
2336         break;
2337
2338     case D3DRS_ZFUNC                     :
2339         {
2340             int glParm = GL_LESS;
2341
2342             switch ((D3DCMPFUNC) Value) {
2343             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2344             case D3DCMP_LESS:          glParm=GL_LESS; break;
2345             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2346             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2347             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2348             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2349             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2350             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2351             default:
2352                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2353             }
2354             glDepthFunc(glParm);
2355             checkGLcall("glDepthFunc");
2356         }
2357         break;
2358
2359     case D3DRS_AMBIENT                   :
2360         {
2361             float col[4];
2362             D3DCOLORTOGLFLOAT4(Value, col);
2363             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2364             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2365             checkGLcall("glLightModel for MODEL_AMBIENT");
2366
2367         }
2368         break;
2369
2370     case D3DRS_ALPHABLENDENABLE          :
2371         if (Value) {
2372             glEnable(GL_BLEND);
2373             checkGLcall("glEnable GL_BLEND");
2374         } else {
2375             glDisable(GL_BLEND);
2376             checkGLcall("glDisable GL_BLEND");
2377         };
2378         break;
2379
2380     case D3DRS_SRCBLEND                  :
2381     case D3DRS_DESTBLEND                 :
2382         {
2383             int newVal = GL_ZERO;
2384             switch (Value) {
2385             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
2386             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
2387             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
2388             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
2389             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
2390             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
2391             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
2392             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
2393             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
2394             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
2395             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
2396
2397             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
2398                 This->srcBlend = newVal;
2399                 This->dstBlend = newVal;
2400                 break;
2401
2402             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
2403                 This->srcBlend = newVal;
2404                 This->dstBlend = newVal;
2405                 break;
2406             default:
2407                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2408             }
2409
2410             if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2411             if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2412             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2413             glBlendFunc(This->srcBlend, This->dstBlend);
2414
2415             checkGLcall("glBlendFunc");
2416         }
2417         break;
2418
2419     case D3DRS_ALPHATESTENABLE           :
2420         if (Value) {
2421             glEnable(GL_ALPHA_TEST);
2422             checkGLcall("glEnable GL_ALPHA_TEST");
2423         } else {
2424             glDisable(GL_ALPHA_TEST);
2425             checkGLcall("glDisable GL_ALPHA_TEST");
2426         }
2427         break;
2428
2429     case D3DRS_ALPHAFUNC                 :
2430         {
2431             int glParm = GL_LESS;
2432             float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2433
2434             switch ((D3DCMPFUNC) Value) {
2435             case D3DCMP_NEVER:         glParm = GL_NEVER; break;
2436             case D3DCMP_LESS:          glParm = GL_LESS; break;
2437             case D3DCMP_EQUAL:         glParm = GL_EQUAL; break;
2438             case D3DCMP_LESSEQUAL:     glParm = GL_LEQUAL; break;
2439             case D3DCMP_GREATER:       glParm = GL_GREATER; break;
2440             case D3DCMP_NOTEQUAL:      glParm = GL_NOTEQUAL; break;
2441             case D3DCMP_GREATEREQUAL:  glParm = GL_GEQUAL; break;
2442             case D3DCMP_ALWAYS:        glParm = GL_ALWAYS; break;
2443             default:
2444                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2445             }
2446             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2447             glAlphaFunc(glParm, ref);
2448             This->alphafunc = glParm;
2449             checkGLcall("glAlphaFunc");
2450         }
2451         break;
2452
2453     case D3DRS_ALPHAREF                  :
2454         {
2455             int glParm = This->alphafunc;
2456             float ref = 1.0f;
2457
2458             ref = ((float) Value) / 255.0f;
2459             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2460             glAlphaFunc(glParm, ref);
2461             checkGLcall("glAlphaFunc");
2462         }
2463         break;
2464
2465     case D3DRS_CLIPPLANEENABLE           :
2466     case D3DRS_CLIPPING                  :
2467         {
2468             /* Ensure we only do the changed clip planes */
2469             DWORD enable  = 0xFFFFFFFF;
2470             DWORD disable = 0x00000000;
2471             
2472             /* If enabling / disabling all */
2473             if (State == D3DRS_CLIPPING) {
2474                 if (Value) {
2475                     enable  = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2476                     disable = 0x00;
2477                 } else {
2478                     disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2479                     enable  = 0x00;
2480                 }
2481             } else {
2482                 enable =   Value & ~OldValue;
2483                 disable = ~Value &  OldValue;
2484             }
2485             
2486             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
2487             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
2488             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
2489             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
2490             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
2491             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
2492             
2493             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2494             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2495             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2496             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2497             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2498             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2499
2500             /** update clipping status */
2501             if (enable) {
2502               This->StateBlock->clip_status.ClipUnion = 0;
2503               This->StateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2504             } else {
2505               This->StateBlock->clip_status.ClipUnion = 0;
2506               This->StateBlock->clip_status.ClipIntersection = 0;
2507             }
2508         }
2509         break;
2510
2511     case D3DRS_BLENDOP                   :
2512         {
2513             int glParm = GL_FUNC_ADD;
2514
2515             switch ((D3DBLENDOP) Value) {
2516             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
2517             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
2518             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2519             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
2520             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
2521             default:
2522                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2523             }
2524             TRACE("glBlendEquation(%x)\n", glParm);
2525             glBlendEquation(glParm);
2526             checkGLcall("glBlendEquation");
2527         }
2528         break;
2529
2530     case D3DRS_TEXTUREFACTOR             :
2531         {
2532             unsigned int i;
2533
2534             /* Note the texture color applies to all textures whereas 
2535                GL_TEXTURE_ENV_COLOR applies to active only */
2536             float col[4];
2537             D3DCOLORTOGLFLOAT4(Value, col);
2538             /* Set the default alpha blend color */
2539             glBlendColor(col[0], col[1], col[2], col[3]);
2540             checkGLcall("glBlendColor");
2541
2542             /* And now the default texture color as well */
2543             for (i = 0; i < GL_LIMITS(textures); i++) {
2544
2545                 /* Note the D3DRS value applies to all textures, but GL has one
2546                    per texture, so apply it now ready to be used!               */
2547                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2548 #if defined(GL_VERSION_1_3)
2549                     glActiveTexture(GL_TEXTURE0 + i);
2550 #else
2551                     glActiveTextureARB(GL_TEXTURE0_ARB + i);
2552 #endif
2553                     checkGLcall("Activate texture.. to update const color");
2554                 } else if (i>0) {
2555                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2556                 }
2557
2558                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2559                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2560             }
2561         }
2562         break;
2563
2564     case D3DRS_SPECULARENABLE            : 
2565         {
2566             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2567                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2568                specular color. This is wrong:
2569                Separate specular color means the specular colour is maintained separately, whereas
2570                single color means it is merged in. However in both cases they are being used to
2571                some extent.
2572                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2573                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2574                   running 1.4 yet!
2575              */
2576               if (Value) {
2577                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2578                 checkGLcall("glMaterialfv");
2579                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2580                   glEnable(GL_COLOR_SUM_EXT);
2581                 } else {
2582                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
2583                 }
2584                 checkGLcall("glEnable(GL_COLOR_SUM)");
2585               } else {
2586                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2587
2588                 /* for the case of enabled lighting: */
2589                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2590                 checkGLcall("glMaterialfv");
2591
2592                 /* for the case of disabled lighting: */
2593                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2594                   glDisable(GL_COLOR_SUM_EXT);
2595                 } else {
2596                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
2597                 }
2598                 checkGLcall("glDisable(GL_COLOR_SUM)");
2599               }
2600         }
2601         break;
2602
2603     case D3DRS_STENCILENABLE             :
2604         if (Value) {
2605             glEnable(GL_STENCIL_TEST);
2606             checkGLcall("glEnable GL_STENCIL_TEST");
2607         } else {
2608             glDisable(GL_STENCIL_TEST);
2609             checkGLcall("glDisable GL_STENCIL_TEST");
2610         }
2611         break;
2612
2613     case D3DRS_STENCILFUNC               :
2614         {
2615            int glParm = GL_ALWAYS;
2616            int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2617            GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2618
2619            switch ((D3DCMPFUNC) Value) {
2620            case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2621            case D3DCMP_LESS:          glParm=GL_LESS; break;
2622            case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2623            case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2624            case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2625            case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2626            case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2627            case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2628            default:
2629                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2630            }
2631            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2632            This->stencilfunc = glParm;
2633            glStencilFunc(glParm, ref, mask);
2634            checkGLcall("glStencilFunc");
2635         }
2636         break;
2637
2638     case D3DRS_STENCILREF                :
2639         {
2640            int glParm = This->stencilfunc;
2641            int ref = 0;
2642            GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2643
2644            ref = Value;
2645            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2646            glStencilFunc(glParm, ref, mask);
2647            checkGLcall("glStencilFunc");
2648         }
2649         break;
2650
2651     case D3DRS_STENCILMASK               :
2652         {
2653            int glParm = This->stencilfunc;
2654            int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2655            GLuint mask = Value;
2656
2657            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2658            glStencilFunc(glParm, ref, mask);
2659            checkGLcall("glStencilFunc");
2660         }
2661         break;
2662
2663     case D3DRS_STENCILFAIL               :
2664         {
2665             GLenum fail  ; 
2666             GLenum zpass ; 
2667             GLenum zfail ; 
2668
2669             fail = StencilOp(Value);
2670             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2671             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2672             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2673             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2674
2675             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2676             glStencilOp(fail, zfail, zpass);
2677             checkGLcall("glStencilOp(fail, zfail, zpass);");
2678         }
2679         break;
2680     case D3DRS_STENCILZFAIL              :
2681         {
2682             GLenum fail  ; 
2683             GLenum zpass ; 
2684             GLenum zfail ; 
2685
2686             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2687             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2688             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2689             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2690             zfail = StencilOp(Value);
2691
2692             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2693             glStencilOp(fail, zfail, zpass);
2694             checkGLcall("glStencilOp(fail, zfail, zpass);");
2695         }
2696         break;
2697     case D3DRS_STENCILPASS               :
2698         {
2699             GLenum fail  ; 
2700             GLenum zpass ; 
2701             GLenum zfail ; 
2702
2703             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2704             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2705             zpass = StencilOp(Value);
2706             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2707             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2708
2709             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2710             glStencilOp(fail, zfail, zpass);
2711             checkGLcall("glStencilOp(fail, zfail, zpass);");
2712         }
2713         break;
2714
2715     case D3DRS_STENCILWRITEMASK          :
2716         {
2717             glStencilMask(Value);
2718             TRACE("glStencilMask(%lu)\n", Value);
2719             checkGLcall("glStencilMask");
2720         }
2721         break;
2722
2723     case D3DRS_FOGENABLE                 :
2724         {
2725           if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2726                glEnable(GL_FOG);
2727                checkGLcall("glEnable GL_FOG");
2728             } else {
2729                glDisable(GL_FOG);
2730                checkGLcall("glDisable GL_FOG");
2731             }
2732         }
2733         break;
2734
2735     case D3DRS_RANGEFOGENABLE            :
2736         {
2737             if (Value) {
2738               TRACE("Enabled RANGEFOG");
2739             } else {
2740               TRACE("Disabled RANGEFOG");
2741             }
2742         }
2743         break;
2744
2745     case D3DRS_FOGCOLOR                  :
2746         {
2747             float col[4];
2748             D3DCOLORTOGLFLOAT4(Value, col);
2749             /* Set the default alpha blend color */
2750             glFogfv(GL_FOG_COLOR, &col[0]);
2751             checkGLcall("glFog GL_FOG_COLOR");
2752         }
2753         break;
2754
2755     case D3DRS_FOGTABLEMODE              :
2756         { 
2757           glHint(GL_FOG_HINT, GL_NICEST);
2758           switch (Value) {
2759           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2760           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2761           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2762           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2763           default:
2764             FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2765           }
2766           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2767             glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2768           }
2769         }
2770         break;
2771
2772     case D3DRS_FOGVERTEXMODE             :
2773         { 
2774           glHint(GL_FOG_HINT, GL_FASTEST);
2775           switch (Value) {
2776           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2777           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2778           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2779           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2780           default:
2781             FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2782           }
2783           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2784             glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2785           }
2786         }
2787         break;
2788
2789     case D3DRS_FOGSTART                  :
2790         {
2791             tmpvalue.d = Value;
2792             glFogfv(GL_FOG_START, &tmpvalue.f);
2793             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2794             TRACE("Fog Start == %f\n", tmpvalue.f);
2795         }
2796         break;
2797
2798     case D3DRS_FOGEND                    :
2799         {
2800             tmpvalue.d = Value;
2801             glFogfv(GL_FOG_END, &tmpvalue.f);
2802             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2803             TRACE("Fog End == %f\n", tmpvalue.f);
2804         }
2805         break;
2806
2807     case D3DRS_FOGDENSITY                :
2808         {
2809             tmpvalue.d = Value;
2810             glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2811             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2812         }
2813         break;
2814
2815     case D3DRS_VERTEXBLEND               :
2816         {
2817           This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2818           TRACE("Vertex Blending state to %ld\n",  Value);
2819         }
2820         break;
2821
2822     case D3DRS_TWEENFACTOR               :
2823         {
2824           tmpvalue.d = Value;
2825           This->UpdateStateBlock->tween_factor = tmpvalue.f;
2826           TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2827         }
2828         break;
2829
2830     case D3DRS_INDEXEDVERTEXBLENDENABLE  :
2831         {
2832           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2833         }
2834         break;
2835
2836     case D3DRS_COLORVERTEX               :
2837     case D3DRS_DIFFUSEMATERIALSOURCE     :
2838     case D3DRS_SPECULARMATERIALSOURCE    :
2839     case D3DRS_AMBIENTMATERIALSOURCE     :
2840     case D3DRS_EMISSIVEMATERIALSOURCE    :
2841         {
2842             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2843
2844             if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2845                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2846                       This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2847                       This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2848                       This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2849                       This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2850
2851                 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2852                     if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2853                         Parm = GL_AMBIENT_AND_DIFFUSE;
2854                     } else {
2855                         Parm = GL_DIFFUSE;
2856                     }
2857                 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2858                     Parm = GL_AMBIENT;
2859                 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2860                     Parm = GL_EMISSION;
2861                 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2862                     Parm = GL_SPECULAR;
2863                 } else {
2864                     Parm = -1;
2865                 }
2866
2867                 if (Parm == -1) {
2868                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2869                 } else {
2870                     This->tracking_color = NEEDS_TRACKING;
2871                     This->tracking_parm  = Parm;
2872                 }
2873
2874             } else {
2875                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2876             }
2877         }
2878         break; 
2879
2880     case D3DRS_LINEPATTERN               :
2881         {
2882             union {
2883                 DWORD           d;
2884                 D3DLINEPATTERN  lp;
2885             } tmppattern;
2886             tmppattern.d = Value;
2887
2888             TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2889
2890             if (tmppattern.lp.wRepeatFactor) {
2891                 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2892                 checkGLcall("glLineStipple(repeat, linepattern)");
2893                 glEnable(GL_LINE_STIPPLE);
2894                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2895             } else {
2896                 glDisable(GL_LINE_STIPPLE);
2897                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2898             }
2899         }
2900         break;
2901
2902     case D3DRS_ZBIAS                     :
2903         {
2904             if (Value) {
2905                 tmpvalue.d = Value;
2906                 TRACE("ZBias value %f\n", tmpvalue.f);
2907                 glPolygonOffset(0, -tmpvalue.f);
2908                 checkGLcall("glPolygonOffset(0, -Value)");
2909                 glEnable(GL_POLYGON_OFFSET_FILL);
2910                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2911                 glEnable(GL_POLYGON_OFFSET_LINE);
2912                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2913                 glEnable(GL_POLYGON_OFFSET_POINT);
2914                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2915             } else {
2916                 glDisable(GL_POLYGON_OFFSET_FILL);
2917                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2918                 glDisable(GL_POLYGON_OFFSET_LINE);
2919                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2920                 glDisable(GL_POLYGON_OFFSET_POINT);
2921                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2922             }
2923         }
2924         break;
2925
2926     case D3DRS_NORMALIZENORMALS          :
2927         if (Value) {
2928             glEnable(GL_NORMALIZE);
2929             checkGLcall("glEnable(GL_NORMALIZE);");
2930         } else {
2931             glDisable(GL_NORMALIZE);
2932             checkGLcall("glDisable(GL_NORMALIZE);");
2933         }
2934         break;
2935
2936     case D3DRS_POINTSIZE                 :
2937         tmpvalue.d = Value;
2938         TRACE("Set point size to %f\n", tmpvalue.f);
2939         glPointSize(tmpvalue.f);
2940         checkGLcall("glPointSize(...);");
2941         break;
2942
2943     case D3DRS_POINTSIZE_MIN             :
2944         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2945           tmpvalue.d = Value;
2946           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2947           checkGLcall("glPointParameterfEXT(...);");
2948         } else {
2949           FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2950         }
2951         break;
2952
2953     case D3DRS_POINTSIZE_MAX             :
2954         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2955           tmpvalue.d = Value;
2956           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2957           checkGLcall("glPointParameterfEXT(...);");
2958         } else {
2959           FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2960         }
2961         break;
2962
2963     case D3DRS_POINTSCALE_A              :
2964     case D3DRS_POINTSCALE_B              :
2965     case D3DRS_POINTSCALE_C              :
2966     case D3DRS_POINTSCALEENABLE          :
2967         {
2968             /* If enabled, supply the parameters, otherwise fall back to defaults */
2969             if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2970                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2971                 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2972                 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2973                 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2974
2975                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2976                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2977                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2978                 } else {
2979                   TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2980                 }
2981             } else {
2982                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2983                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2984                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2985                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2986                 } else {
2987                   TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2988                 }
2989             }
2990             break;
2991         }
2992
2993     case D3DRS_COLORWRITEENABLE          :
2994       {
2995         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n", 
2996               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
2997               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2998               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
2999               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0); 
3000         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE, 
3001                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3002                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE, 
3003                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3004         checkGLcall("glColorMask(...)");
3005       }
3006       break;
3007
3008     case D3DRS_LOCALVIEWER               :
3009       {
3010         GLint state = (Value) ? 1 : 0;
3011         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);    
3012         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3013       }
3014       break;
3015
3016     case D3DRS_LASTPIXEL                 :
3017       {
3018         if (Value) {
3019           TRACE("Last Pixel Drawing Enabled\n");  
3020         } else {
3021           FIXME("Last Pixel Drawing Disabled, not handled yet\n");  
3022         }
3023       }
3024       break;
3025
3026     case D3DRS_SOFTWAREVERTEXPROCESSING  :
3027       {
3028         if (Value) {
3029           TRACE("Software Processing Enabled\n");  
3030         } else {
3031           TRACE("Software Processing Disabled\n");  
3032         }
3033       }
3034       break;
3035
3036       /** not supported */
3037     case D3DRS_ZVISIBLE                  :
3038       {
3039         LEAVE_GL();
3040         return D3DERR_INVALIDCALL;
3041       }
3042
3043         /* Unhandled yet...! */
3044     case D3DRS_EDGEANTIALIAS             :
3045     case D3DRS_WRAP0                     :
3046     case D3DRS_WRAP1                     :
3047     case D3DRS_WRAP2                     :
3048     case D3DRS_WRAP3                     :
3049     case D3DRS_WRAP4                     :
3050     case D3DRS_WRAP5                     :
3051     case D3DRS_WRAP6                     :
3052     case D3DRS_WRAP7                     :
3053     case D3DRS_POINTSPRITEENABLE         :
3054     case D3DRS_MULTISAMPLEANTIALIAS      :
3055     case D3DRS_MULTISAMPLEMASK           :
3056     case D3DRS_PATCHEDGESTYLE            :
3057     case D3DRS_PATCHSEGMENTS             :
3058     case D3DRS_DEBUGMONITORTOKEN         :
3059     case D3DRS_POSITIONORDER             :
3060     case D3DRS_NORMALORDER               :
3061         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3062         FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3063         break;
3064     default:
3065         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3066     }
3067
3068     LEAVE_GL();
3069
3070     return D3D_OK;
3071 }
3072 HRESULT  WINAPI  IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3073     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3074     TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3075     *pValue = This->StateBlock->renderstate[State];
3076     return D3D_OK;
3077 }
3078 HRESULT  WINAPI  IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3079   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3080   
3081   TRACE("(%p)\n", This);
3082   
3083   return IDirect3DDeviceImpl_BeginStateBlock(This);
3084 }
3085 HRESULT  WINAPI  IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3086   IDirect3DStateBlockImpl* pSB;
3087   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3088   HRESULT res;
3089
3090   TRACE("(%p)\n", This);
3091
3092   res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3093   *pToken = (DWORD) pSB;
3094   return res;
3095 }
3096
3097 HRESULT  WINAPI  IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3098   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3099   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3100
3101   TRACE("(%p)\n", This);
3102
3103   return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3104
3105 }
3106 HRESULT  WINAPI  IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3107   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3108   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3109
3110   TRACE("(%p)\n", This);
3111
3112   return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3113 }
3114 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3115   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3116   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3117
3118   TRACE("(%p)\n", This);
3119
3120   return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3121 }
3122
3123 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3124   IDirect3DStateBlockImpl* pSB;
3125   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3126   HRESULT res;
3127
3128   TRACE("(%p) : for type %d\n", This, Type);
3129
3130   res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3131   *pToken = (DWORD) pSB;
3132   return res;
3133 }
3134
3135 HRESULT  WINAPI  IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3136     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3137     FIXME("(%p) : stub\n", This);
3138     if (NULL == pClipStatus) {
3139       return D3DERR_INVALIDCALL;
3140     }
3141     This->UpdateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3142     This->UpdateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3143     return D3D_OK;
3144 }
3145 HRESULT  WINAPI  IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3146     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3147     FIXME("(%p) : stub\n", This);    
3148     if (NULL == pClipStatus) {
3149       return D3DERR_INVALIDCALL;
3150     }
3151     pClipStatus->ClipUnion = This->UpdateStateBlock->clip_status.ClipUnion;
3152     pClipStatus->ClipIntersection = This->UpdateStateBlock->clip_status.ClipIntersection;
3153     return D3D_OK;
3154 }
3155 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3156     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3157     TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3158     *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3159     if (*ppTexture)
3160         IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3161     return D3D_OK;
3162 }
3163 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3164
3165     IDirect3DBaseTexture8 *oldTxt;
3166     BOOL reapplyStates = TRUE;
3167     INT oldTextureDimensions = -1;
3168     DWORD reapplyFlags = 0;
3169
3170     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3171     D3DRESOURCETYPE textureType;
3172
3173     oldTxt = This->UpdateStateBlock->textures[Stage];
3174     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3175
3176     /* Reject invalid texture units */
3177     if (Stage >= GL_LIMITS(textures)) {
3178         TRACE("Attempt to access invalid texture rejected\n");
3179         return D3DERR_INVALIDCALL;
3180     }
3181
3182     This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3183     This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3184     This->UpdateStateBlock->textures[Stage] = pTexture;
3185
3186     /* Handle recording of state blocks */
3187     if (This->isRecordingState) {
3188         TRACE("Recording... not performing anything\n");
3189         return D3D_OK;
3190     }
3191
3192     oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3193     ENTER_GL();
3194
3195     /* Make appropriate texture active */
3196     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3197 #if defined(GL_VERSION_1_3)
3198         glActiveTexture(GL_TEXTURE0 + Stage);
3199         checkGLcall("glActiveTexture");
3200 #else
3201         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3202         checkGLcall("glActiveTextureARB");
3203 #endif
3204     } else if (Stage>0) {
3205         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3206     }
3207
3208     /* Decrement the count of the previous texture */
3209     if (NULL != oldTxt) {
3210         IDirect3DBaseTexture8Impl_Release(oldTxt);
3211     }
3212
3213     if (NULL != pTexture) {
3214         IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3215
3216         /* Now setup the texture appropraitly */
3217         textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3218
3219         if (textureType == D3DRTYPE_TEXTURE) {
3220           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3221             TRACE("Skipping setting texture as old == new\n");
3222             reapplyStates = FALSE;
3223           } else {
3224             /* Standard 2D texture */
3225             TRACE("Standard 2d texture\n");
3226             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3227
3228             /* Load up the texture now */
3229             IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3230           }
3231         } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3232           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3233             TRACE("Skipping setting texture as old == new\n");
3234             reapplyStates = FALSE;
3235           } else {
3236             /* Standard 3D (volume) texture */
3237             TRACE("Standard 3d texture\n");
3238             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3239
3240             /* Load up the texture now */
3241             IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3242           }
3243         } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3244           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3245             TRACE("Skipping setting texture as old == new\n");
3246             reapplyStates = FALSE;
3247           } else {
3248             /* Standard Cube texture */
3249             TRACE("Standard Cube texture\n");
3250             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3251
3252             /* Load up the texture now */
3253             IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3254           }
3255         } else {
3256             FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3257         }
3258     } else {
3259         TRACE("Setting to no texture (ie default texture)\n");
3260         This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3261         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3262         checkGLcall("glBindTexture");
3263         TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3264     }
3265
3266     /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3267     if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3268        glDisable(oldTextureDimensions);
3269        checkGLcall("Disable oldTextureDimensions");
3270        if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3271           glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3272           checkGLcall("glEnable new texture dimensions");
3273        }
3274
3275        /* If Alpha arg1 is texture then handle the special case when there changes between a
3276           texture and no texture - See comments in set_tex_op                                  */
3277        if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) && 
3278            (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3279        {
3280            reapplyFlags |= REAPPLY_ALPHAOP;
3281        }
3282     }
3283
3284
3285     /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3286        a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3287     if (reapplyStates) {
3288        setupTextureStates(iface, Stage, reapplyFlags);
3289     }
3290
3291     LEAVE_GL();   
3292
3293     return D3D_OK;
3294 }
3295
3296 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3297     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3298     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3299     *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3300     return D3D_OK;
3301 }
3302
3303 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3304     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3305     union {
3306         float f;
3307         DWORD d;
3308     } tmpvalue;
3309
3310     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3311    
3312     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3313
3314     /* Reject invalid texture units */
3315     if (Stage >= GL_LIMITS(textures)) {
3316         TRACE("Attempt to access invalid texture rejected\n");
3317         return D3DERR_INVALIDCALL;
3318     }
3319
3320     This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3321     This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3322     This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3323
3324     /* Handle recording of state blocks */
3325     if (This->isRecordingState) {
3326         TRACE("Recording... not performing anything\n");
3327         return D3D_OK;
3328     }
3329
3330     ENTER_GL();
3331
3332     /* Make appropriate texture active */
3333     VTRACE(("Activating appropriate texture state %ld\n", Stage));
3334     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3335 #if defined(GL_VERSION_1_3)
3336         glActiveTexture(GL_TEXTURE0 + Stage);
3337         vcheckGLcall("glActiveTexture");
3338 #else
3339         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3340         vcheckGLcall("glActiveTextureARB");
3341 #endif
3342     } else if (Stage > 0) {
3343         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3344     }
3345
3346     switch (Type) {
3347
3348     case D3DTSS_MINFILTER             :
3349     case D3DTSS_MIPFILTER             :
3350         {
3351             DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3352             DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3353             GLint realVal = GL_LINEAR;
3354
3355             if (ValueMIN == D3DTEXF_NONE) {
3356               /* Doesn't really make sense - Windows just seems to disable
3357                  mipmapping when this occurs                              */
3358               FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3359               realVal = GL_LINEAR;
3360             } else if (ValueMIN == D3DTEXF_POINT) {
3361                 /* GL_NEAREST_* */
3362               if (ValueMIP == D3DTEXF_NONE) {
3363                     realVal = GL_NEAREST;
3364                 } else if (ValueMIP == D3DTEXF_POINT) {
3365                     realVal = GL_NEAREST_MIPMAP_NEAREST;
3366                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3367                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3368                 } else {
3369                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3370                     realVal = GL_NEAREST;
3371                 }
3372             } else if (ValueMIN == D3DTEXF_LINEAR) {
3373                 /* GL_LINEAR_* */
3374                 if (ValueMIP == D3DTEXF_NONE) {
3375                     realVal = GL_LINEAR;
3376                 } else if (ValueMIP == D3DTEXF_POINT) {
3377                     realVal = GL_LINEAR_MIPMAP_NEAREST;
3378                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3379                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3380                 } else {
3381                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3382                     realVal = GL_LINEAR;
3383                 }
3384             } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3385               if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3386                 if (ValueMIP == D3DTEXF_NONE) {
3387                   realVal = GL_LINEAR_MIPMAP_LINEAR;              
3388                 } else if (ValueMIP == D3DTEXF_POINT) {
3389                   realVal = GL_LINEAR_MIPMAP_NEAREST;
3390                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3391                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3392                 } else {
3393                   FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3394                   realVal = GL_LINEAR;
3395                 }
3396               } else {
3397                 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3398                 realVal = GL_LINEAR;
3399               }
3400             } else {
3401                 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3402                 realVal = GL_LINEAR_MIPMAP_LINEAR;
3403             }
3404
3405             TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3406             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3407             checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3408             /**
3409              * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3410              */
3411             if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3412               glTexParameteri(This->StateBlock->textureDimensions[Stage], 
3413                               GL_TEXTURE_MAX_ANISOTROPY_EXT, 
3414                               This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3415               checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3416             }
3417         }
3418         break;
3419
3420     case D3DTSS_MAGFILTER             :
3421       {
3422         DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3423         GLint realVal = GL_NEAREST;
3424
3425         if (ValueMAG == D3DTEXF_POINT) {
3426           realVal = GL_NEAREST;
3427         } else if (ValueMAG == D3DTEXF_LINEAR) {
3428           realVal = GL_LINEAR;
3429         } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3430           if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3431             realVal = GL_LINEAR;
3432           } else {
3433             FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3434             realVal = GL_NEAREST;
3435           }
3436         } else {
3437           FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3438           realVal = GL_NEAREST;
3439         }
3440         TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3441         glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3442         checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3443         /**
3444          * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3445          */
3446         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3447           glTexParameteri(This->StateBlock->textureDimensions[Stage], 
3448                           GL_TEXTURE_MAX_ANISOTROPY_EXT, 
3449                           This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3450           checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3451         }
3452       }
3453       break;
3454
3455     case D3DTSS_MAXMIPLEVEL           :
3456       {
3457         /**
3458          * Not really the same, but the more apprioprate than nothing
3459          */
3460         glTexParameteri(This->StateBlock->textureDimensions[Stage], 
3461                         GL_TEXTURE_BASE_LEVEL, 
3462                         This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3463         checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3464       }
3465       break;
3466
3467     case D3DTSS_MAXANISOTROPY         :
3468       { 
3469         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3470           glTexParameteri(This->StateBlock->textureDimensions[Stage], 
3471                           GL_TEXTURE_MAX_ANISOTROPY_EXT, 
3472                           This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3473           checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3474         }
3475       }
3476       break;
3477
3478     case D3DTSS_MIPMAPLODBIAS         :
3479       { 
3480         if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3481           tmpvalue.d = Value;
3482           glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, 
3483                     GL_TEXTURE_LOD_BIAS_EXT,
3484                     tmpvalue.f);
3485           checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3486         }
3487       }
3488       break;
3489
3490     case D3DTSS_ALPHAOP               :
3491     case D3DTSS_COLOROP               :
3492         {
3493
3494             if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3495                 /* TODO: Disable by making this and all later levels disabled */
3496                 glDisable(GL_TEXTURE_1D);
3497                 checkGLcall("Disable GL_TEXTURE_1D");
3498                 glDisable(GL_TEXTURE_2D);
3499                 checkGLcall("Disable GL_TEXTURE_2D");
3500                 glDisable(GL_TEXTURE_3D);
3501                 checkGLcall("Disable GL_TEXTURE_3D");
3502                 break; /* Don't bother setting the texture operations */
3503             } else {
3504                 /* Enable only the appropriate texture dimension */
3505                 if (Type == D3DTSS_COLOROP) {
3506                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3507                         glEnable(GL_TEXTURE_1D);
3508                         checkGLcall("Enable GL_TEXTURE_1D");
3509                     } else {
3510                         glDisable(GL_TEXTURE_1D);
3511                         checkGLcall("Disable GL_TEXTURE_1D");
3512                     } 
3513                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3514                       if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3515                         glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3516                         checkGLcall("Enable GL_TEXTURE_2D");
3517                       } else {
3518                         glEnable(GL_TEXTURE_2D);
3519                         checkGLcall("Enable GL_TEXTURE_2D");
3520                       }
3521                     } else {
3522                         glDisable(GL_TEXTURE_2D);
3523                         checkGLcall("Disable GL_TEXTURE_2D");
3524                     }
3525                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3526                         glEnable(GL_TEXTURE_3D);
3527                         checkGLcall("Enable GL_TEXTURE_3D");
3528                     } else {
3529                         glDisable(GL_TEXTURE_3D);
3530                         checkGLcall("Disable GL_TEXTURE_3D");
3531                     }
3532                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3533                         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3534                         checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3535                     } else {
3536                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3537                         checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3538                     }
3539                 }
3540             }
3541             /* Drop through... (Except disable case) */
3542         case D3DTSS_COLORARG0             :
3543         case D3DTSS_COLORARG1             :
3544         case D3DTSS_COLORARG2             :
3545         case D3DTSS_ALPHAARG0             :
3546         case D3DTSS_ALPHAARG1             :
3547         case D3DTSS_ALPHAARG2             :
3548             {
3549                 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 || 
3550                                    Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3551                 if (isAlphaArg) {
3552                     set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3553                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1], 
3554                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2], 
3555                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3556                 } else {
3557                     set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3558                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1], 
3559                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2], 
3560                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3561                 }
3562             }
3563             break;
3564         }
3565
3566     case D3DTSS_ADDRESSU              :
3567     case D3DTSS_ADDRESSV              :
3568     case D3DTSS_ADDRESSW              :
3569         {
3570             GLint wrapParm = GL_REPEAT;
3571
3572             switch (Value) {
3573             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
3574             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;      
3575             case D3DTADDRESS_BORDER: 
3576               {
3577                 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3578                   wrapParm = GL_CLAMP_TO_BORDER_ARB; 
3579                 } else {
3580                   /* FIXME: Not right, but better */
3581                   FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3582                   wrapParm = GL_REPEAT; 
3583                 }
3584               }
3585               break;
3586             case D3DTADDRESS_MIRROR: 
3587               {
3588                 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3589                   wrapParm = GL_MIRRORED_REPEAT_ARB;
3590                 } else {
3591                   /* Unsupported in OpenGL pre-1.4 */
3592                   FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3593                   wrapParm = GL_REPEAT;
3594                 }
3595               }
3596               break;
3597             case D3DTADDRESS_MIRRORONCE: 
3598               {
3599                 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3600                   wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3601                 } else {
3602                   FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3603                   wrapParm = GL_REPEAT; 
3604                 }
3605               }
3606               break;
3607
3608             default:
3609                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3610                 wrapParm = GL_REPEAT; 
3611             }
3612
3613             switch (Type) {
3614             case D3DTSS_ADDRESSU:
3615                 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3616                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3617                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3618                 break;
3619             case D3DTSS_ADDRESSV:
3620                 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3621                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3622                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3623                 break;
3624             case D3DTSS_ADDRESSW:
3625                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3626                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3627                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3628                 break;
3629             default: /* nop */
3630                 break; /** stupic compilator */
3631             }
3632         }
3633         break;
3634
3635     case D3DTSS_BORDERCOLOR           :
3636         {
3637             float col[4];
3638             D3DCOLORTOGLFLOAT4(Value, col);
3639             TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value); 
3640             glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3641             checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3642         }
3643         break;
3644
3645     case D3DTSS_TEXCOORDINDEX         :
3646         {
3647             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3648
3649             /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include 
3650                   one flag, you can still specify an index value, which the system uses to 
3651                   determine the texture wrapping mode.  
3652                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3653                   means use the vertex position (camera-space) as the input texture coordinates 
3654                   for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render 
3655                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3656                   to the TEXCOORDINDEX value */
3657           
3658             /** 
3659              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos 
3660              */
3661             switch (Value & 0xFFFF0000) {
3662             case D3DTSS_TCI_PASSTHRU:
3663               /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3664               glDisable(GL_TEXTURE_GEN_S);
3665               glDisable(GL_TEXTURE_GEN_T);
3666               glDisable(GL_TEXTURE_GEN_R);
3667               checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3668               break;
3669
3670             case D3DTSS_TCI_CAMERASPACEPOSITION:
3671               /* CameraSpacePosition means use the vertex position, transformed to camera space, 
3672                  as the input texture coordinates for this stage's texture transformation. This 
3673                  equates roughly to EYE_LINEAR                                                  */
3674               {
3675                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3676                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3677                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3678                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3679                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3680
3681                 glMatrixMode(GL_MODELVIEW);
3682                 glPushMatrix();
3683                 glLoadIdentity();
3684                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3685                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3686                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3687                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3688                 glPopMatrix();
3689                 
3690                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3691                 glEnable(GL_TEXTURE_GEN_S);
3692                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3693                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3694                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3695                 glEnable(GL_TEXTURE_GEN_T);
3696                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3697                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3698                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3699                 glEnable(GL_TEXTURE_GEN_R);
3700                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3701                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3702                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3703               }
3704               break;
3705
3706             case D3DTSS_TCI_CAMERASPACENORMAL:
3707               {
3708                 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3709                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3710                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3711                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3712                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3713                   TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3714
3715                   glMatrixMode(GL_MODELVIEW);
3716                   glPushMatrix();
3717                   glLoadIdentity();
3718                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3719                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3720                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3721                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3722                   glPopMatrix();
3723                   
3724                   glEnable(GL_TEXTURE_GEN_S);
3725                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3726                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3727                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3728                   glEnable(GL_TEXTURE_GEN_T);
3729                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3730                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3731                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3732                   glEnable(GL_TEXTURE_GEN_R);
3733                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3734                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3735                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3736                 }
3737               }
3738               break;
3739
3740             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3741               {
3742                 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3743                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3744                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3745                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3746                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3747                   TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3748                   
3749                   glMatrixMode(GL_MODELVIEW);
3750                   glPushMatrix();
3751                   glLoadIdentity();
3752                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3753                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3754                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3755                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3756                   glPopMatrix();
3757                   
3758                   glEnable(GL_TEXTURE_GEN_S);
3759                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3760                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3761                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3762                   glEnable(GL_TEXTURE_GEN_T);
3763                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3764                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3765                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3766                   glEnable(GL_TEXTURE_GEN_R);
3767                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3768                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3769                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3770                 }
3771               }
3772               break;
3773
3774             /* Unhandled types: */
3775             default:
3776                 /* Todo: */
3777                 /* ? disable GL_TEXTURE_GEN_n ? */ 
3778                 glDisable(GL_TEXTURE_GEN_S);
3779                 glDisable(GL_TEXTURE_GEN_T);
3780                 glDisable(GL_TEXTURE_GEN_R);
3781                 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3782                 break;
3783             }
3784         }
3785         break;
3786
3787         /* Unhandled */
3788     case D3DTSS_TEXTURETRANSFORMFLAGS :
3789         set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3790         break; 
3791
3792     case D3DTSS_BUMPENVMAT00          :
3793     case D3DTSS_BUMPENVMAT01          :
3794         TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3795         break;
3796     case D3DTSS_BUMPENVMAT10          :
3797     case D3DTSS_BUMPENVMAT11          :
3798         TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3799         break;
3800
3801     case D3DTSS_BUMPENVLSCALE         :
3802       TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3803       break;
3804
3805     case D3DTSS_BUMPENVLOFFSET        :
3806       TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3807       break;
3808
3809     case D3DTSS_RESULTARG             :
3810       TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3811       break;
3812
3813     default:
3814         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3815         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3816     }
3817
3818     LEAVE_GL();
3819
3820     return D3D_OK;
3821 }
3822 HRESULT  WINAPI  IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3823     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3824     TRACE("(%p) : stub\n", This);    /* FIXME: Needs doing, but called often and is harmless */
3825     return D3D_OK;
3826 }
3827 HRESULT  WINAPI  IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3828     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3829     FIXME("(%p) : stub\n", This);    
3830     return D3D_OK;
3831 }
3832 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3833     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3834     FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3835           pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3836     if (PaletteNumber >= MAX_PALETTES) {
3837         return D3DERR_INVALIDCALL;
3838     }
3839     memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3840     return D3D_OK;
3841 }
3842 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3843     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3844     if (PaletteNumber >= MAX_PALETTES) {
3845         return D3DERR_INVALIDCALL;
3846     }
3847     memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3848     FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3849           pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3850     return D3D_OK;
3851 }
3852 HRESULT  WINAPI  IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3853     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3854     FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3855     if (PaletteNumber >= MAX_PALETTES) {
3856         return D3DERR_INVALIDCALL;
3857     }
3858     This->currentPalette = PaletteNumber;
3859
3860 #if defined(GL_EXT_paletted_texture)
3861     if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3862
3863       ENTER_GL();
3864
3865       GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D,    /* target */
3866                                   GL_RGBA,          /* internal format */
3867                                   256,              /* table size */
3868                                   GL_RGBA,          /* table format */
3869                                   GL_UNSIGNED_BYTE, /* table type */
3870                                   This->palettes[PaletteNumber]);
3871       checkGLcall("glColorTableEXT");
3872
3873       LEAVE_GL();
3874
3875     } else {
3876       /* Delayed palette handling ... waiting for software emulation into preload code */
3877     }
3878 #endif
3879     return D3D_OK;
3880 }
3881 HRESULT  WINAPI  IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3882     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3883     *PaletteNumber = This->currentPalette;
3884     FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3885     return D3D_OK;
3886 }
3887 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3888
3889     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3890     This->StateBlock->streamIsUP = FALSE;
3891
3892     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3893     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3894
3895     return D3D_OK;
3896 }
3897 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3898                                                            UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3899     UINT idxStride = 2;
3900     IDirect3DIndexBuffer8      *pIB;
3901     D3DINDEXBUFFER_DESC         IdxBufDsc;
3902
3903     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3904     pIB = This->StateBlock->pIndexData;
3905     This->StateBlock->streamIsUP = FALSE;
3906
3907     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, 
3908           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3909           minIndex, NumVertices, startIndex, primCount);
3910
3911     IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3912     if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3913         idxStride = 2;
3914     } else {
3915         idxStride = 4;
3916     }
3917
3918     drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3919                    minIndex);
3920
3921     return D3D_OK;
3922 }
3923 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3924     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3925
3926     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), 
3927           PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3928
3929     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3930
3931     /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3932     This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData; 
3933     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3934     This->StateBlock->streamIsUP = TRUE;
3935     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3936     This->StateBlock->stream_stride[0] = 0;
3937     This->StateBlock->stream_source[0] = NULL;
3938
3939     /*stream zero settings set to null at end */
3940     return D3D_OK;
3941 }
3942 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3943                                                              UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3944                                                              D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3945                                                              UINT VertexStreamZeroStride) {
3946     int idxStride;
3947     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3948     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),
3949           MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,  IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3950
3951     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3952     if (IndexDataFormat == D3DFMT_INDEX16) {
3953         idxStride = 2;
3954     } else {
3955         idxStride = 4;
3956     }
3957
3958     /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3959     This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3960     This->StateBlock->streamIsUP = TRUE;
3961     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3962     drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3963
3964     /*stream zero settings set to null at end */
3965     This->StateBlock->stream_source[0] = NULL;
3966     This->StateBlock->stream_stride[0] = 0;
3967     IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3968
3969     return D3D_OK;
3970 }
3971 HRESULT  WINAPI  IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3972     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3973     FIXME("(%p) : stub\n", This);    return D3D_OK;
3974 }
3975 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3976     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3977     IDirect3DVertexShaderImpl* object;
3978     IDirect3DVertexShaderDeclarationImpl* attached_decl;
3979     HRESULT res;
3980     UINT i;
3981
3982     TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3983     if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3984       return D3DERR_INVALIDCALL;
3985     }
3986     for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3987     if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3988       return D3DERR_OUTOFVIDEOMEMORY;
3989     }
3990
3991     /** Create the Vertex Shader */
3992     res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3993     /** TODO: check FAILED(res) */
3994
3995     /** Create and Bind the Vertex Shader Declaration */
3996     res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3997     /** TODO: check FAILED(res) */
3998
3999     VertexShaders[i] = object;
4000     VertexShaderDeclarations[i] = attached_decl;
4001     *pHandle = VS_HIGHESTFIXEDFXF + i;
4002     TRACE("Finished creating vertex shader %lx\n", *pHandle);
4003
4004     return D3D_OK;
4005 }
4006 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4007     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4008
4009     This->UpdateStateBlock->VertexShader = Handle;
4010     This->UpdateStateBlock->Changed.vertexShader = TRUE;
4011     This->UpdateStateBlock->Set.vertexShader = TRUE;
4012     
4013     if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4014       TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
4015       This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4016       This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4017       This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4018     } else { /* use a fvf, so desactivate the vshader decl */
4019       TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4020       This->UpdateStateBlock->vertexShaderDecl = NULL;
4021       This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4022       This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4023     }
4024     /* Handle recording of state blocks */
4025     if (This->isRecordingState) {
4026       TRACE("Recording... not performing anything\n");
4027       return D3D_OK;
4028     }
4029     /**
4030      * TODO: merge HAL shaders context switching from prototype
4031      */
4032     return D3D_OK;
4033 }
4034 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4035     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4036     TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4037     *pHandle = This->StateBlock->VertexShader;
4038     return D3D_OK;
4039 }
4040
4041 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4042     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4043     IDirect3DVertexShaderImpl* object; 
4044     IDirect3DVertexShaderDeclarationImpl* attached_decl;
4045
4046     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4047       return D3DERR_INVALIDCALL;
4048     }
4049
4050     /**
4051      * Delete Vertex Shader
4052      */
4053     object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4054     if (NULL == object) {
4055       return D3DERR_INVALIDCALL;
4056     }
4057     TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4058     /* TODO: check validity of object */
4059     if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4060     if (object->prgId != 0) {
4061         GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4062     }
4063     HeapFree(GetProcessHeap(), 0, (void *)object->data);
4064     HeapFree(GetProcessHeap(), 0, (void *)object);
4065     VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4066
4067     /**
4068      * Delete Vertex Shader Declaration
4069      */
4070     attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4071     if (NULL == attached_decl) {
4072       return D3DERR_INVALIDCALL;
4073     } 
4074     TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4075     /* TODO: check validity of object */
4076     HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4077     HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4078     VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4079
4080     return D3D_OK;
4081 }
4082
4083 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4084   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4085
4086   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4087     ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4088     return D3DERR_INVALIDCALL;
4089   }
4090   if (NULL == pConstantData) {
4091     return D3DERR_INVALIDCALL;
4092   }
4093   if (ConstantCount > 1) {
4094     FLOAT* f = (FLOAT*)pConstantData;
4095     UINT i;
4096     TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4097     for (i = 0; i < ConstantCount; ++i) {
4098       TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4099       f += 4;
4100     }
4101   } else { 
4102     FLOAT* f = (FLOAT*) pConstantData;
4103     TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4104   }
4105   This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4106   memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4107   return D3D_OK;
4108 }
4109 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4110   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4111
4112   TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4113   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4114     return D3DERR_INVALIDCALL;
4115   }
4116   if (NULL == pConstantData) {
4117     return D3DERR_INVALIDCALL;
4118   }
4119   memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4120   return D3D_OK;
4121 }
4122 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4123   /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4124   IDirect3DVertexShaderDeclarationImpl* attached_decl;
4125   
4126   attached_decl = VERTEX_SHADER_DECL(Handle);
4127   if (NULL == attached_decl) {
4128     return D3DERR_INVALIDCALL;
4129   }
4130   return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4131 }
4132 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4133   /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4134   IDirect3DVertexShaderImpl* object;
4135   
4136   object = VERTEX_SHADER(Handle);
4137   if (NULL == object) {
4138     return D3DERR_INVALIDCALL;
4139   }
4140   return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4141 }
4142
4143 HRESULT  WINAPI  IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4144     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4145     IDirect3DIndexBuffer8 *oldIdxs;
4146
4147     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4148     oldIdxs = This->StateBlock->pIndexData;
4149
4150     This->UpdateStateBlock->Changed.Indices = TRUE;
4151     This->UpdateStateBlock->Set.Indices = TRUE;
4152     This->UpdateStateBlock->pIndexData = pIndexData;
4153     This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4154
4155     /* Handle recording of state blocks */
4156     if (This->isRecordingState) {
4157         TRACE("Recording... not performing anything\n");
4158         return D3D_OK;
4159     }
4160
4161     if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4162     if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4163     return D3D_OK;
4164 }
4165 HRESULT  WINAPI  IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4166     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4167     FIXME("(%p) : stub\n", This);
4168
4169     *ppIndexData = This->StateBlock->pIndexData;
4170     /* up ref count on ppindexdata */
4171     if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4172     *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4173
4174     return D3D_OK;
4175 }
4176 HRESULT  WINAPI  IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4177     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4178     IDirect3DPixelShaderImpl* object;
4179     HRESULT res;
4180     UINT i;
4181
4182     TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4183     if (NULL == pFunction || NULL == pHandle) {
4184       return D3DERR_INVALIDCALL;
4185     }
4186     for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4187     if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4188       return D3DERR_OUTOFVIDEOMEMORY;
4189     }
4190
4191     /** Create the Pixel Shader */
4192     res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4193     if (SUCCEEDED(res)) {
4194       PixelShaders[i] = object;
4195       *pHandle = VS_HIGHESTFIXEDFXF + i;
4196       return D3D_OK;
4197     } 
4198     *pHandle = 0xFFFFFFFF;
4199     return res;
4200 }
4201
4202 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4203     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4204
4205     This->UpdateStateBlock->PixelShader = Handle;
4206     This->UpdateStateBlock->Changed.pixelShader = TRUE;
4207     This->UpdateStateBlock->Set.pixelShader = TRUE;
4208
4209     /* Handle recording of state blocks */
4210     if (This->isRecordingState) {
4211         TRACE_(d3d_shader)("Recording... not performing anything\n");
4212         return D3D_OK;
4213     }
4214
4215     if (Handle != 0) {
4216       TRACE_(d3d_shader)("(%p) : Set pixel shader with handle %lx\n", This, Handle);
4217     } else {
4218       TRACE_(d3d_shader)("(%p) : Remove pixel shader\n", This);
4219     }
4220
4221     return D3D_OK;
4222 }
4223
4224 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4225     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4226     TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4227     *pHandle = This->StateBlock->PixelShader;
4228     return D3D_OK;
4229 }
4230
4231 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4232     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4233     IDirect3DPixelShaderImpl* object;   
4234
4235     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4236       return D3DERR_INVALIDCALL;
4237     }
4238     object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4239     if (NULL == object) {
4240       return D3DERR_INVALIDCALL;
4241     }
4242     TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4243     /* TODO: check validity of object before free */
4244     if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4245     if (object->prgId != 0) {
4246         GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4247     }
4248     HeapFree(GetProcessHeap(), 0, (void *)object->data);
4249     HeapFree(GetProcessHeap(), 0, (void *)object);
4250     PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4251
4252     return D3D_OK;
4253 }
4254
4255 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4256   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4257
4258   if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4259     ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4260     return D3DERR_INVALIDCALL;
4261   }
4262   if (NULL == pConstantData) {
4263     return D3DERR_INVALIDCALL;
4264   }
4265   if (ConstantCount > 1) {
4266     FLOAT* f = (FLOAT*)pConstantData;
4267     UINT i;
4268     TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4269     for (i = 0; i < ConstantCount; ++i) {
4270       TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4271       f += 4;
4272     }
4273   } else { 
4274     FLOAT* f = (FLOAT*) pConstantData;
4275     TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4276   }
4277   This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4278   memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4279   return D3D_OK;
4280 }
4281 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4282   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4283
4284   TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4285   if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4286     return D3DERR_INVALIDCALL;
4287   }
4288   if (NULL == pConstantData) {
4289     return D3DERR_INVALIDCALL;
4290   }
4291   memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4292   return D3D_OK;
4293 }
4294 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4295     IDirect3DPixelShaderImpl* object;
4296
4297     object = PIXEL_SHADER(Handle);
4298     if (NULL == object) {
4299       return D3DERR_INVALIDCALL;
4300     } 
4301     return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4302 }
4303 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4304     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4305     FIXME("(%p) : stub\n", This);    return D3D_OK;
4306 }
4307 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4308     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4309     FIXME("(%p) : stub\n", This);    return D3D_OK;
4310 }
4311 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4312     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4313     FIXME("(%p) : stub\n", This);    return D3D_OK;
4314 }
4315
4316 HRESULT  WINAPI  IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4317     IDirect3DVertexBuffer8 *oldSrc;
4318     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4319
4320     oldSrc = This->StateBlock->stream_source[StreamNumber];
4321     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4322
4323     This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4324     This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4325     This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4326     This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4327
4328     /* Handle recording of state blocks */
4329     if (This->isRecordingState) {
4330         TRACE("Recording... not performing anything\n");
4331         return D3D_OK;
4332     }
4333
4334     if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4335     if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4336     return D3D_OK;
4337 }
4338 HRESULT  WINAPI  IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4339     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4340     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4341     *pStream = This->StateBlock->stream_source[StreamNumber];
4342     *pStride = This->StateBlock->stream_stride[StreamNumber];
4343     IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4344     return D3D_OK;
4345 }
4346
4347
4348 IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
4349 {
4350     IDirect3DDevice8Impl_QueryInterface,
4351     IDirect3DDevice8Impl_AddRef,
4352     IDirect3DDevice8Impl_Release,
4353     IDirect3DDevice8Impl_TestCooperativeLevel,
4354     IDirect3DDevice8Impl_GetAvailableTextureMem,
4355     IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4356     IDirect3DDevice8Impl_GetDirect3D,
4357     IDirect3DDevice8Impl_GetDeviceCaps,
4358     IDirect3DDevice8Impl_GetDisplayMode,
4359     IDirect3DDevice8Impl_GetCreationParameters,
4360     IDirect3DDevice8Impl_SetCursorProperties,
4361     IDirect3DDevice8Impl_SetCursorPosition,
4362     IDirect3DDevice8Impl_ShowCursor,
4363     IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4364     IDirect3DDevice8Impl_Reset,
4365     IDirect3DDevice8Impl_Present,
4366     IDirect3DDevice8Impl_GetBackBuffer,
4367     IDirect3DDevice8Impl_GetRasterStatus,
4368     IDirect3DDevice8Impl_SetGammaRamp,
4369     IDirect3DDevice8Impl_GetGammaRamp,
4370     IDirect3DDevice8Impl_CreateTexture,
4371     IDirect3DDevice8Impl_CreateVolumeTexture,
4372     IDirect3DDevice8Impl_CreateCubeTexture,
4373     IDirect3DDevice8Impl_CreateVertexBuffer,
4374     IDirect3DDevice8Impl_CreateIndexBuffer,
4375     IDirect3DDevice8Impl_CreateRenderTarget,
4376     IDirect3DDevice8Impl_CreateDepthStencilSurface,
4377     IDirect3DDevice8Impl_CreateImageSurface,
4378     IDirect3DDevice8Impl_CopyRects,
4379     IDirect3DDevice8Impl_UpdateTexture,
4380     IDirect3DDevice8Impl_GetFrontBuffer,
4381     IDirect3DDevice8Impl_SetRenderTarget,
4382     IDirect3DDevice8Impl_GetRenderTarget,
4383     IDirect3DDevice8Impl_GetDepthStencilSurface,
4384     IDirect3DDevice8Impl_BeginScene,
4385     IDirect3DDevice8Impl_EndScene,
4386     IDirect3DDevice8Impl_Clear,
4387     IDirect3DDevice8Impl_SetTransform,
4388     IDirect3DDevice8Impl_GetTransform,
4389     IDirect3DDevice8Impl_MultiplyTransform,
4390     IDirect3DDevice8Impl_SetViewport,
4391     IDirect3DDevice8Impl_GetViewport,
4392     IDirect3DDevice8Impl_SetMaterial,
4393     IDirect3DDevice8Impl_GetMaterial,
4394     IDirect3DDevice8Impl_SetLight,
4395     IDirect3DDevice8Impl_GetLight,
4396     IDirect3DDevice8Impl_LightEnable,
4397     IDirect3DDevice8Impl_GetLightEnable,
4398     IDirect3DDevice8Impl_SetClipPlane,
4399     IDirect3DDevice8Impl_GetClipPlane,
4400     IDirect3DDevice8Impl_SetRenderState,
4401     IDirect3DDevice8Impl_GetRenderState,
4402     IDirect3DDevice8Impl_BeginStateBlock,
4403     IDirect3DDevice8Impl_EndStateBlock,
4404     IDirect3DDevice8Impl_ApplyStateBlock,
4405     IDirect3DDevice8Impl_CaptureStateBlock,
4406     IDirect3DDevice8Impl_DeleteStateBlock,
4407     IDirect3DDevice8Impl_CreateStateBlock,
4408     IDirect3DDevice8Impl_SetClipStatus,
4409     IDirect3DDevice8Impl_GetClipStatus,
4410     IDirect3DDevice8Impl_GetTexture,
4411     IDirect3DDevice8Impl_SetTexture,
4412     IDirect3DDevice8Impl_GetTextureStageState,
4413     IDirect3DDevice8Impl_SetTextureStageState,
4414     IDirect3DDevice8Impl_ValidateDevice,
4415     IDirect3DDevice8Impl_GetInfo,
4416     IDirect3DDevice8Impl_SetPaletteEntries,
4417     IDirect3DDevice8Impl_GetPaletteEntries,
4418     IDirect3DDevice8Impl_SetCurrentTexturePalette,
4419     IDirect3DDevice8Impl_GetCurrentTexturePalette,
4420     IDirect3DDevice8Impl_DrawPrimitive,
4421     IDirect3DDevice8Impl_DrawIndexedPrimitive,
4422     IDirect3DDevice8Impl_DrawPrimitiveUP,
4423     IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4424     IDirect3DDevice8Impl_ProcessVertices,
4425     IDirect3DDevice8Impl_CreateVertexShader,
4426     IDirect3DDevice8Impl_SetVertexShader,
4427     IDirect3DDevice8Impl_GetVertexShader,
4428     IDirect3DDevice8Impl_DeleteVertexShader,
4429     IDirect3DDevice8Impl_SetVertexShaderConstant,
4430     IDirect3DDevice8Impl_GetVertexShaderConstant,
4431     IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4432     IDirect3DDevice8Impl_GetVertexShaderFunction,
4433     IDirect3DDevice8Impl_SetStreamSource,
4434     IDirect3DDevice8Impl_GetStreamSource,
4435     IDirect3DDevice8Impl_SetIndices,
4436     IDirect3DDevice8Impl_GetIndices,
4437     IDirect3DDevice8Impl_CreatePixelShader,
4438     IDirect3DDevice8Impl_SetPixelShader,
4439     IDirect3DDevice8Impl_GetPixelShader,
4440     IDirect3DDevice8Impl_DeletePixelShader,
4441     IDirect3DDevice8Impl_SetPixelShaderConstant,
4442     IDirect3DDevice8Impl_GetPixelShaderConstant,
4443     IDirect3DDevice8Impl_GetPixelShaderFunction,
4444     IDirect3DDevice8Impl_DrawRectPatch,
4445     IDirect3DDevice8Impl_DrawTriPatch,
4446     IDirect3DDevice8Impl_DeletePatch
4447 };
4448
4449 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4450 {
4451 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4452   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4453
4454   ENTER_GL();
4455
4456 #if 0
4457   if (This->glCtx != This->render_ctx) {
4458     glXDestroyContext(This->display, This->render_ctx);
4459     This->render_ctx = This->glCtx;
4460   }
4461 #endif
4462   if (This->win != This->drawable) {
4463     glXDestroyPbuffer(This->display, This->drawable);
4464     This->drawable = This->win;
4465   }
4466
4467   LEAVE_GL();
4468
4469 #endif
4470   return D3D_OK;
4471 }
4472
4473 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4474                                                 IDirect3DSurface8* RenderSurface, 
4475                                                 IDirect3DSurface8* StencilSurface) {
4476
4477   HRESULT ret =  D3DERR_INVALIDCALL; 
4478   /**
4479    * Currently only active for GLX >= 1.3
4480    * for others versions we'll have to use GLXPixmaps
4481    *
4482    * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4483    * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4484    * so only check OpenGL version
4485    */
4486 #if defined(GL_VERSION_1_3) 
4487   GLXFBConfig* cfgs = NULL;
4488   int nCfgs = 0;
4489   int attribs[256];
4490   int nAttribs = 0;
4491   D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4492   D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4493   UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4494   UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4495   IDirect3DSurface8Impl* tmp;
4496
4497   IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4498  
4499 #define PUSH1(att)        attribs[nAttribs++] = (att); 
4500 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4501
4502   PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4503   PUSH2(GLX_X_RENDERABLE,  TRUE);
4504   PUSH2(GLX_DOUBLEBUFFER, TRUE);
4505   
4506   switch (BackBufferFormat) {
4507     /* color buffer */
4508   case D3DFMT_P8:
4509     PUSH2(GLX_RENDER_TYPE,  GLX_COLOR_INDEX_BIT);
4510     PUSH2(GLX_BUFFER_SIZE,  8);
4511     PUSH2(GLX_DOUBLEBUFFER, TRUE);
4512     break;
4513     
4514   case D3DFMT_R3G3B2:
4515     PUSH2(GLX_RENDER_TYPE,  GLX_RGBA_BIT);
4516     PUSH2(GLX_RED_SIZE,     3);
4517     PUSH2(GLX_GREEN_SIZE,   3);
4518     PUSH2(GLX_BLUE_SIZE,    2);
4519     break;
4520     
4521   case D3DFMT_A1R5G5B5:
4522     PUSH2(GLX_ALPHA_SIZE,   1);
4523   case D3DFMT_X1R5G5B5:
4524     PUSH2(GLX_RED_SIZE,     5);
4525     PUSH2(GLX_GREEN_SIZE,   5);
4526     PUSH2(GLX_BLUE_SIZE,    5);
4527     break;
4528     
4529   case D3DFMT_R5G6B5:
4530     PUSH2(GLX_RED_SIZE,     5);
4531     PUSH2(GLX_GREEN_SIZE,   6);
4532     PUSH2(GLX_BLUE_SIZE,    5);
4533     break;
4534     
4535   case D3DFMT_A4R4G4B4:
4536     PUSH2(GLX_ALPHA_SIZE,   4);
4537   case D3DFMT_X4R4G4B4:
4538     PUSH2(GLX_RED_SIZE,     4);
4539     PUSH2(GLX_GREEN_SIZE,   4);
4540     PUSH2(GLX_BLUE_SIZE,    4);
4541     break;
4542     
4543   case D3DFMT_A8R8G8B8:
4544     PUSH2(GLX_ALPHA_SIZE,   8);
4545   case D3DFMT_R8G8B8:
4546   case D3DFMT_X8R8G8B8:
4547     PUSH2(GLX_RED_SIZE,     8);
4548     PUSH2(GLX_GREEN_SIZE,   8);
4549     PUSH2(GLX_BLUE_SIZE,    8);
4550     break;
4551
4552   default:
4553     break;
4554   }
4555    
4556   switch (StencilBufferFormat) { 
4557   case D3DFMT_D16_LOCKABLE:
4558   case D3DFMT_D16:
4559     PUSH2(GLX_DEPTH_SIZE,   16);
4560     break;
4561     
4562   case D3DFMT_D15S1:
4563     PUSH2(GLX_DEPTH_SIZE,   15);
4564     break;
4565     
4566   case D3DFMT_D24X8:
4567     PUSH2(GLX_DEPTH_SIZE,   24);
4568     break;
4569     
4570   case D3DFMT_D24X4S4:
4571     PUSH2(GLX_DEPTH_SIZE,   24);
4572     PUSH2(GLX_STENCIL_SIZE, 4);
4573     break;
4574     
4575   case D3DFMT_D24S8:
4576     PUSH2(GLX_DEPTH_SIZE,   24);
4577     PUSH2(GLX_STENCIL_SIZE, 8);
4578     break;
4579     
4580   case D3DFMT_D32:
4581     PUSH2(GLX_DEPTH_SIZE,   32);
4582     break;
4583
4584   default:
4585     break;
4586   }
4587
4588   PUSH1(None);
4589   
4590   ENTER_GL();
4591
4592   cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4593   if (NULL != cfgs) {
4594 #ifdef EXTRA_TRACES
4595     int i;
4596     for (i = 0; i < nCfgs; ++i) {
4597       TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4598     }
4599 #endif
4600
4601     if (NULL != This->renderTarget) {
4602       /*GLenum prev_read; */
4603       glFlush();
4604       vcheckGLcall("glFlush");
4605
4606 #ifdef EXTRA_TRACES
4607       /** very very usefull debug code */
4608       glXSwapBuffers(This->display, This->drawable);   
4609       printf("Hit Enter to get next frame ...\n");
4610       getchar();
4611 #endif
4612
4613 #if 0
4614       glGetIntegerv(GL_READ_BUFFER, &prev_read);
4615       vcheckGLcall("glIntegerv");
4616       glReadBuffer(GL_BACK);
4617       vcheckGLcall("glReadBuffer");
4618       {
4619         long j;
4620         long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4621
4622         if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4623             pitch = pitch / 2;
4624
4625         for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4626           glReadPixels(0, 
4627                        This->renderTarget->myDesc.Height - j - 1, 
4628                        This->renderTarget->myDesc.Width, 
4629                        1,
4630                        D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format), 
4631                        D3DFmt2GLType(This, This->renderTarget->myDesc.Format), 
4632                        This->renderTarget->allocatedMemory + j * pitch);
4633           vcheckGLcall("glReadPixels");
4634         }
4635       }      
4636       glReadBuffer(prev_read);
4637       vcheckGLcall("glReadBuffer");
4638 #endif
4639     }
4640
4641     if (BackBufferFormat != This->renderTarget->myDesc.Format && 
4642         StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4643       nAttribs = 0;
4644       PUSH2(GLX_PBUFFER_WIDTH,  Width);
4645       PUSH2(GLX_PBUFFER_HEIGHT, Height);
4646       PUSH1(None);
4647       This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4648             
4649       This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4650       if (NULL == This->render_ctx) {
4651         ERR("cannot create glxContext\n"); 
4652       }
4653
4654       glFlush();
4655       glXSwapBuffers(This->display, This->drawable);
4656       if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4657         TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4658       }
4659       checkGLcall("glXMakeContextCurrent");
4660     }
4661
4662     tmp = This->renderTarget;
4663     This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4664     IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4665     IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4666
4667     tmp = This->stencilBufferTarget;
4668     This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4669     if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4670     if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4671
4672     {
4673       DWORD value;
4674       /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4675       This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4676       /* Force updating the cull mode */
4677       IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4678       IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4679       /* Force updating projection matrix */
4680       This->last_was_rhw = FALSE;
4681       This->proj_valid = FALSE;
4682     }
4683
4684     ret = D3D_OK;
4685
4686   } else {
4687     ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4688   }
4689
4690 #undef PUSH1
4691 #undef PUSH2
4692
4693   LEAVE_GL();
4694
4695 #endif
4696
4697   return ret;
4698 }