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