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