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