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