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