Culling to different viewports failed as clearing the whole viewport
[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     glEnable(GL_SCISSOR_TEST);
1353     checkGLcall("glEnable GL_SCISSOR_TEST");
1354     if (Count > 0 && pRects) {
1355         glEnable(GL_SCISSOR_TEST);
1356         checkGLcall("glEnable GL_SCISSOR_TEST");
1357         curRect = pRects;
1358     } else {
1359         curRect = NULL;
1360     }
1361
1362     /* Only set the values up once, as they are not changing */
1363     if (Flags & D3DCLEAR_STENCIL) {     
1364         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1365         glClearStencil(Stencil);
1366         checkGLcall("glClearStencil");
1367         glMask = glMask | GL_STENCIL_BUFFER_BIT;
1368     }
1369
1370     if (Flags & D3DCLEAR_ZBUFFER) {
1371         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1372         glDepthMask(GL_TRUE); 
1373         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1374         glClearDepth(Z);
1375         checkGLcall("glClearDepth");
1376         glMask = glMask | GL_DEPTH_BUFFER_BIT;
1377     }
1378
1379     if (Flags & D3DCLEAR_TARGET) {
1380         TRACE("Clearing screen with glClear to color %lx\n", Color);
1381         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1382         glClearColor(((Color >> 16) & 0xFF) / 255.0f, 
1383                      ((Color >>  8) & 0xFF) / 255.0f,
1384                      ((Color >>  0) & 0xFF) / 255.0f, 
1385                      ((Color >> 24) & 0xFF) / 255.0f);
1386         checkGLcall("glClearColor");
1387         glMask = glMask | GL_COLOR_BUFFER_BIT;
1388     }
1389
1390     /* Now process each rect in turn */
1391     for (i = 0; i < Count || i == 0; i++) {
1392
1393         if (curRect) {
1394             /* Note gl uses lower left, width/height */
1395             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1396                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1397                   curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2), 
1398                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1399             glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2), 
1400                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1401             checkGLcall("glScissor");
1402         } else {
1403             glScissor(This->StateBlock->viewport.X, 
1404                       (This->PresentParms.BackBufferHeight - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)), 
1405                       This->StateBlock->viewport.Width, 
1406                       This->StateBlock->viewport.Height);
1407             checkGLcall("glScissor");
1408         }
1409
1410         /* Clear the selected rectangle (or full screen) */
1411         glClear(glMask);
1412         checkGLcall("glClear");
1413
1414         /* Step to the next rectangle */
1415         if (curRect) curRect = curRect + sizeof(D3DRECT);
1416     }
1417
1418     /* Restore the old values (why..?) */
1419     if (Flags & D3DCLEAR_STENCIL) {
1420         glClearStencil(old_stencil_clear_value);
1421     }    
1422     if (Flags & D3DCLEAR_ZBUFFER) {
1423         glDepthMask(old_ztest);
1424         glClearDepth(old_z_clear_value);
1425     }
1426     if (Flags & D3DCLEAR_TARGET) {
1427         glClearColor(old_color_clear_value[0], 
1428                      old_color_clear_value[1],
1429                      old_color_clear_value[2], 
1430                      old_color_clear_value[3]);
1431     }
1432
1433     if (Count > 0 && pRects) {
1434         glDisable(GL_SCISSOR_TEST);
1435         checkGLcall("glDisable");
1436     }
1437     LEAVE_GL();
1438
1439     return D3D_OK;
1440 }
1441 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1442     ICOM_THIS(IDirect3DDevice8Impl,iface);
1443     int k;
1444
1445     /* Most of this routine, comments included copied from ddraw tree initially: */
1446     TRACE("(%p) : State=%d\n", This, d3dts);
1447
1448     /* Handle recording of state blocks */
1449     if (This->isRecordingState) {
1450         TRACE("Recording... not performing anything\n");
1451         This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1452         This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1453         memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1454         return D3D_OK;
1455     }
1456
1457     /*
1458      * if the new matrix is the same as the current one,
1459      * we cut off any further processing. this seems to be a reasonable
1460      * optimization because as was noticed, some apps (warcraft3 for example)
1461      * tend towards setting the same matrix repeatedly for some dumb reason.
1462      *
1463      * From here on we assume that the new matrix is different, wherever it matters
1464      * but note
1465      */
1466     if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1467         TRACE("The app is setting the same matrix over again\n");
1468         return D3D_OK;
1469     } else {
1470         conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1471     }
1472
1473     /*
1474        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1475        where ViewMat = Camera space, WorldMat = world space.
1476
1477        In OpenGL, camera and world space is combined into GL_MODELVIEW
1478        matrix.  The Projection matrix stay projection matrix. 
1479      */
1480
1481     /* Capture the times we can just ignore the change */
1482     if (d3dts == D3DTS_WORLDMATRIX(0)) {
1483         This->modelview_valid = FALSE;
1484         return D3D_OK;
1485
1486     } else if (d3dts == D3DTS_PROJECTION) {
1487         This->proj_valid = FALSE;
1488         return D3D_OK;
1489
1490     } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511  */
1491         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1492         FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1493         return D3D_OK;
1494     } 
1495     
1496     /* Chances are we really are going to have to change a matrix */
1497     ENTER_GL();
1498
1499     if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1500         if (d3dts < GL_LIMITS(textures)) {
1501             int tex = d3dts - D3DTS_TEXTURE0;
1502 #if defined(GL_VERSION_1_3)
1503             glActiveTexture(GL_TEXTURE0 + tex);
1504 #else 
1505             glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1506 #endif
1507             set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1508         }
1509
1510     } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1511
1512         PLIGHTINFOEL *lightChain = NULL;
1513         float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1514         This->modelview_valid = FALSE;
1515         This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1516         glMatrixMode(GL_MODELVIEW);
1517         checkGLcall("glMatrixMode(GL_MODELVIEW)");
1518         glPushMatrix();
1519         glLoadMatrixf((float *)lpmatrix);
1520         checkGLcall("glLoadMatrixf(...)");
1521
1522         /* If we are changing the View matrix, reset the light and clipping planes to the new view   
1523          * NOTE: We have to reset the positions even if the light/plane is not currently
1524          *       enabled, since the call to enable it will not reset the position.                 
1525          * NOTE2: Apparently texture transforms do NOT need reapplying
1526          */
1527
1528         /* Reset lights */
1529         lightChain = This->StateBlock->lights;
1530         while (lightChain && lightChain->glIndex != -1) {
1531             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1532             checkGLcall("glLightfv posn");
1533             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1534             checkGLcall("glLightfv dirn");
1535             lightChain = lightChain->next;
1536         }
1537         /* Reset Clipping Planes if clipping is enabled */
1538         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1539             glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1540             checkGLcall("glClipPlane");
1541         }
1542         glPopMatrix();
1543
1544     } else { /* What was requested!?? */
1545         WARN("invalid matrix specified: %i\n", d3dts);
1546
1547     }
1548
1549     /* Release lock, all done */
1550     LEAVE_GL();
1551     return D3D_OK;
1552
1553 }
1554 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1555     ICOM_THIS(IDirect3DDevice8Impl,iface);
1556     TRACE("(%p) : for State %d\n", This, State);
1557     memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1558     return D3D_OK;
1559 }
1560
1561 HRESULT  WINAPI  IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1562     D3DMATRIX *mat = NULL;
1563     D3DMATRIX temp;
1564
1565     /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1566         but works regardless of recording being on. 
1567         If this is found to be wrong, change to StateBlock.                             */
1568     ICOM_THIS(IDirect3DDevice8Impl,iface);
1569     TRACE("(%p) : For state %u\n", This, State);
1570
1571     if (State < HIGHEST_TRANSFORMSTATE)
1572     {
1573         mat = &This->UpdateStateBlock->transforms[State];
1574     } else {
1575         FIXME("Unhandled transform state!!\n");
1576     }
1577
1578     /* Copied from ddraw code:  */
1579     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);
1580     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);
1581     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);
1582     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);
1583
1584     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);
1585     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);
1586     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);
1587     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);
1588
1589     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);
1590     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);
1591     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);
1592     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);
1593
1594     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);
1595     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);
1596     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);
1597     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);
1598
1599     /* Apply change via set transform - will reapply to eg. lights this way */
1600     IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1601     return D3D_OK;
1602 }
1603 HRESULT  WINAPI  IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1604     ICOM_THIS(IDirect3DDevice8Impl,iface);
1605
1606     TRACE("(%p)\n", This);
1607     This->UpdateStateBlock->Changed.viewport = TRUE;
1608     This->UpdateStateBlock->Set.viewport = TRUE;
1609     memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1610
1611     /* Handle recording of state blocks */
1612     if (This->isRecordingState) {
1613         TRACE("Recording... not performing anything\n");
1614         return D3D_OK;
1615     }
1616
1617     ENTER_GL();
1618
1619     TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1620           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1621
1622     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1623     checkGLcall("glDepthRange");
1624     /* Note: GL requires lower left, DirectX supplies upper left */
1625     glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)), 
1626                pViewport->Width, pViewport->Height);
1627     checkGLcall("glViewport");
1628
1629     LEAVE_GL();
1630
1631     return D3D_OK;
1632
1633 }
1634 HRESULT  WINAPI  IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1635     ICOM_THIS(IDirect3DDevice8Impl,iface);
1636     TRACE("(%p)\n", This);
1637     memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1638     return D3D_OK;
1639 }
1640
1641 HRESULT  WINAPI  IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1642     ICOM_THIS(IDirect3DDevice8Impl,iface);
1643
1644     This->UpdateStateBlock->Changed.material = TRUE;
1645     This->UpdateStateBlock->Set.material = TRUE;
1646     memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1647
1648     /* Handle recording of state blocks */
1649     if (This->isRecordingState) {
1650         TRACE("Recording... not performing anything\n");
1651         return D3D_OK;
1652     }
1653
1654     ENTER_GL();
1655     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1656     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1657     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1658     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1659     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1660
1661     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1662     checkGLcall("glMaterialfv");
1663     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1664     checkGLcall("glMaterialfv");
1665
1666     /* Only change material color if specular is enabled, otherwise it is set to black */
1667     if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1668        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1669        checkGLcall("glMaterialfv");
1670     } else {
1671        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1672        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1673        checkGLcall("glMaterialfv");
1674     }
1675     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1676     checkGLcall("glMaterialfv");
1677     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1678     checkGLcall("glMaterialf");
1679
1680     LEAVE_GL();
1681     return D3D_OK;
1682 }
1683 HRESULT  WINAPI  IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1684     ICOM_THIS(IDirect3DDevice8Impl,iface);
1685     memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1686     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1687     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1688     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1689     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1690     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1691     return D3D_OK;
1692 }
1693
1694 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1695    you can reference any indexes you want as long as that number max are enabled are any
1696    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1697    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1698    but when recording, just build a chain pretty much of commands to be replayed.                  */
1699    
1700 HRESULT  WINAPI  IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1701     float rho;
1702     PLIGHTINFOEL *object, *temp;
1703
1704     ICOM_THIS(IDirect3DDevice8Impl,iface);
1705     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1706
1707     /* If recording state block, just add to end of lights chain */
1708     if (This->isRecordingState) {
1709         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1710         if (NULL == object) {
1711             return D3DERR_OUTOFVIDEOMEMORY;
1712         }
1713         memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1714         object->OriginalIndex = Index;
1715         object->glIndex = -1;
1716         object->changed = TRUE;
1717
1718         /* Add to the END of the chain of lights changes to be replayed */
1719         if (This->UpdateStateBlock->lights == NULL) {
1720             This->UpdateStateBlock->lights = object;
1721         } else {
1722             temp = This->UpdateStateBlock->lights;
1723             while (temp->next != NULL) temp=temp->next;
1724             temp->next = object;
1725         }
1726         TRACE("Recording... not performing anything more\n");
1727         return D3D_OK;
1728     }
1729
1730     /* Ok, not recording any longer so do real work */
1731     object = This->StateBlock->lights;
1732     while (object != NULL && object->OriginalIndex != Index) object = object->next;
1733
1734     /* If we didnt find it in the list of lights, time to add it */
1735     if (object == NULL) {
1736         PLIGHTINFOEL *insertAt,*prevPos;
1737
1738         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1739         if (NULL == object) {
1740             return D3DERR_OUTOFVIDEOMEMORY;
1741         }
1742         object->OriginalIndex = Index;
1743         object->glIndex = -1;
1744
1745         /* Add it to the front of list with the idea that lights will be changed as needed 
1746            BUT after any lights currently assigned GL indexes                             */
1747         insertAt = This->StateBlock->lights;
1748         prevPos  = NULL;
1749         while (insertAt != NULL && insertAt->glIndex != -1) {
1750             prevPos  = insertAt;
1751             insertAt = insertAt->next;
1752         }
1753
1754         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1755             This->StateBlock->lights = object;
1756         } else if (insertAt == NULL) { /* End of list */
1757             prevPos->next = object;
1758             object->prev = prevPos;
1759         } else { /* Middle of chain */
1760             if (prevPos == NULL) {
1761                 This->StateBlock->lights = object;
1762             } else {
1763                 prevPos->next = object;
1764             }
1765             object->prev = prevPos;
1766             object->next = insertAt;
1767             insertAt->prev = object;
1768         }
1769     }
1770
1771     /* Initialze the object */
1772     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,
1773           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1774           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1775           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1776     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1777           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1778     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1779
1780     /* Save away the information */
1781     memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1782
1783     switch (pLight->Type) {
1784     case D3DLIGHT_POINT:
1785         /* Position */
1786         object->lightPosn[0] = pLight->Position.x;
1787         object->lightPosn[1] = pLight->Position.y;
1788         object->lightPosn[2] = pLight->Position.z;
1789         object->lightPosn[3] = 1.0f;
1790         object->cutoff = 180.0f;
1791         /* FIXME: Range */
1792         break;
1793
1794     case D3DLIGHT_SPOT:
1795         /* Position */
1796         object->lightPosn[0] = pLight->Position.x;
1797         object->lightPosn[1] = pLight->Position.y;
1798         object->lightPosn[2] = pLight->Position.z;
1799         object->lightPosn[3] = 1.0;
1800
1801         /* Direction */
1802         object->lightDirn[0] = pLight->Direction.x;
1803         object->lightDirn[1] = pLight->Direction.y;
1804         object->lightDirn[2] = pLight->Direction.z;
1805         object->lightDirn[3] = 1.0;
1806
1807         /*
1808          * opengl-ish and d3d-ish spot lights use too different models for the
1809          * light "intensity" as a function of the angle towards the main light direction,
1810          * so we only can approximate very roughly.
1811          * however spot lights are rather rarely used in games (if ever used at all).
1812          * furthermore if still used, probably nobody pays attention to such details.
1813          */
1814         if (pLight->Falloff == 0) {
1815             rho = 6.28f;
1816         } else {
1817             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1818         }
1819         if (rho < 0.0001) rho = 0.0001f;
1820         object->exponent = -0.3/log(cos(rho/2));
1821         object->cutoff = pLight->Phi*90/M_PI;
1822
1823         /* FIXME: Range */
1824         break;
1825
1826     case D3DLIGHT_DIRECTIONAL:
1827         /* Direction */
1828         object->lightPosn[0] = -pLight->Direction.x;
1829         object->lightPosn[1] = -pLight->Direction.y;
1830         object->lightPosn[2] = -pLight->Direction.z;
1831         object->lightPosn[3] = 0.0;
1832         object->exponent     = 0.0f;
1833         object->cutoff       = 180.0f;
1834         break;
1835
1836     default:
1837         FIXME("Unrecognized light type %d\n", pLight->Type);
1838     }
1839
1840     /* Update the live definitions if the light is currently assigned a glIndex */
1841     if (object->glIndex != -1) {
1842         setup_light(iface, object->glIndex, object);
1843     }
1844     return D3D_OK;
1845 }
1846 HRESULT  WINAPI  IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1847     PLIGHTINFOEL *lightInfo = NULL;
1848     ICOM_THIS(IDirect3DDevice8Impl,iface); 
1849     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1850     
1851     /* Locate the light in the live lights */
1852     lightInfo = This->StateBlock->lights;
1853     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1854
1855     if (lightInfo == NULL) {
1856         TRACE("Light information requested but light not defined\n");
1857         return D3DERR_INVALIDCALL;
1858     }
1859
1860     memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1861     return D3D_OK;
1862 }
1863 HRESULT  WINAPI  IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1864     PLIGHTINFOEL *lightInfo = NULL;
1865     ICOM_THIS(IDirect3DDevice8Impl,iface);
1866     TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1867
1868     /* If recording state block, just add to end of lights chain with changedEnable set to true */
1869     if (This->isRecordingState) {
1870         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1871         if (NULL == lightInfo) {
1872             return D3DERR_OUTOFVIDEOMEMORY;
1873         }
1874         lightInfo->OriginalIndex = Index;
1875         lightInfo->glIndex = -1;
1876         lightInfo->enabledChanged = TRUE;
1877
1878         /* Add to the END of the chain of lights changes to be replayed */
1879         if (This->UpdateStateBlock->lights == NULL) {
1880             This->UpdateStateBlock->lights = lightInfo;
1881         } else {
1882             PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1883             while (temp->next != NULL) temp=temp->next;
1884             temp->next = lightInfo;
1885         }
1886         TRACE("Recording... not performing anything more\n");
1887         return D3D_OK;
1888     }
1889
1890     /* Not recording... So, locate the light in the live lights */
1891     lightInfo = This->StateBlock->lights;
1892     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1893
1894     /* Special case - enabling an undefined light creates one with a strict set of parms! */
1895     if (lightInfo == NULL) {
1896         D3DLIGHT8 lightParms;
1897         /* Warning - untested code :-) Prob safe to change fixme to a trace but
1898              wait until someone confirms it seems to work!                     */
1899         TRACE("Light enabled requested but light not defined, so defining one!\n"); 
1900         lightParms.Type = D3DLIGHT_DIRECTIONAL;
1901         lightParms.Diffuse.r = 1.0;
1902         lightParms.Diffuse.g = 1.0;
1903         lightParms.Diffuse.b = 1.0;
1904         lightParms.Diffuse.a = 0.0;
1905         lightParms.Specular.r = 0.0;
1906         lightParms.Specular.g = 0.0;
1907         lightParms.Specular.b = 0.0;
1908         lightParms.Specular.a = 0.0;
1909         lightParms.Ambient.r = 0.0;
1910         lightParms.Ambient.g = 0.0;
1911         lightParms.Ambient.b = 0.0;
1912         lightParms.Ambient.a = 0.0;
1913         lightParms.Position.x = 0.0;
1914         lightParms.Position.y = 0.0;
1915         lightParms.Position.z = 0.0;
1916         lightParms.Direction.x = 0.0;
1917         lightParms.Direction.y = 0.0;
1918         lightParms.Direction.z = 1.0;
1919         lightParms.Range = 0.0;
1920         lightParms.Falloff = 0.0;
1921         lightParms.Attenuation0 = 0.0;
1922         lightParms.Attenuation1 = 0.0;
1923         lightParms.Attenuation2 = 0.0;
1924         lightParms.Theta = 0.0;
1925         lightParms.Phi = 0.0;
1926         IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1927
1928         /* Search for it again! Should be fairly quick as near head of list */
1929         lightInfo = This->StateBlock->lights;
1930         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1931         if (lightInfo == NULL) {
1932             FIXME("Adding default lights has failed dismally\n");
1933             return D3DERR_INVALIDCALL;
1934         }
1935     }
1936
1937     /* OK, we now have a light... */
1938     if (Enable == FALSE) {
1939
1940         /* If we are disabling it, check it was enabled, and
1941            still only do something if it has assigned a glIndex (which it should have!)   */
1942         if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1943             TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1944             ENTER_GL();
1945             glDisable(GL_LIGHT0 + lightInfo->glIndex);
1946             checkGLcall("glDisable GL_LIGHT0+Index");
1947             LEAVE_GL();
1948         } else {
1949             TRACE("Nothing to do as light was not enabled\n");
1950         }
1951         lightInfo->lightEnabled = FALSE;
1952     } else {
1953
1954         /* We are enabling it. If it is enabled, its really simple */
1955         if (lightInfo->lightEnabled == TRUE) {
1956             /* nop */
1957             TRACE("Nothing to do as light was enabled\n");
1958
1959         /* If it already has a glIndex, its still simple */
1960         } else if (lightInfo->glIndex != -1) {
1961             TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1962             lightInfo->lightEnabled = TRUE;
1963             ENTER_GL();
1964             glEnable(GL_LIGHT0 + lightInfo->glIndex);
1965             checkGLcall("glEnable GL_LIGHT0+Index already setup");
1966             LEAVE_GL();
1967
1968         /* Otherwise got to find space - lights are ordered gl indexes first */
1969         } else {
1970             PLIGHTINFOEL *bsf  = NULL;
1971             PLIGHTINFOEL *pos  = This->StateBlock->lights;
1972             PLIGHTINFOEL *prev = NULL;
1973             int           Index= 0;
1974             int           glIndex = -1;
1975
1976             /* Try to minimize changes as much as possible */
1977             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1978
1979                 /* Try to remember which index can be replaced if necessary */
1980                 if (bsf==NULL && pos->lightEnabled == FALSE) {
1981                     /* Found a light we can replace, save as best replacement */
1982                     bsf = pos;
1983                 }
1984
1985                 /* Step to next space */
1986                 prev = pos;
1987                 pos = pos->next;
1988                 Index ++;
1989             }
1990
1991             /* If we have too many active lights, fail the call */
1992             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1993                 FIXME("Program requests too many concurrent lights\n");
1994                 return D3DERR_INVALIDCALL;
1995
1996             /* If we have allocated all lights, but not all are enabled,
1997                reuse one which is not enabled                           */
1998             } else if (Index == This->maxConcurrentLights) {
1999                 /* use bsf - Simply swap the new light and the BSF one */
2000                 PLIGHTINFOEL *bsfNext = bsf->next;
2001                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2002
2003                 /* Sort out ends */
2004                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2005                 if (bsf->prev != NULL) {
2006                     bsf->prev->next = lightInfo;
2007                 } else {
2008                     This->StateBlock->lights = lightInfo;
2009                 }
2010
2011                 /* If not side by side, lots of chains to update */
2012                 if (bsf->next != lightInfo) {
2013                     lightInfo->prev->next = bsf;
2014                     bsf->next->prev = lightInfo;
2015                     bsf->next       = lightInfo->next;
2016                     bsf->prev       = lightInfo->prev;
2017                     lightInfo->next = bsfNext;
2018                     lightInfo->prev = bsfPrev;
2019
2020                 } else {
2021                     /* Simple swaps */
2022                     bsf->prev = lightInfo;
2023                     bsf->next = lightInfo->next;
2024                     lightInfo->next = bsf;
2025                     lightInfo->prev = bsfPrev;
2026                 }
2027
2028
2029                 /* Update states */
2030                 glIndex = bsf->glIndex;
2031                 bsf->glIndex = -1;
2032                 lightInfo->glIndex = glIndex;
2033                 lightInfo->lightEnabled = TRUE;
2034
2035                 /* Finally set up the light in gl itself */
2036                 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2037                 ENTER_GL();
2038                 setup_light(iface, glIndex, lightInfo);
2039                 glEnable(GL_LIGHT0 + glIndex);
2040                 checkGLcall("glEnable GL_LIGHT0 new setup");
2041                 LEAVE_GL();
2042
2043             /* If we reached the end of the allocated lights, with space in the
2044                gl lights, setup a new light                                     */
2045             } else if (pos->glIndex == -1) {
2046
2047                 /* We reached the end of the allocated gl lights, so already 
2048                     know the index of the next one!                          */
2049                 glIndex = Index;
2050                 lightInfo->glIndex = glIndex;
2051                 lightInfo->lightEnabled = TRUE;
2052
2053                 /* In an ideal world, its already in the right place */
2054                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2055                    /* No need to move it */
2056                 } else {
2057                     /* Remove this light from the list */
2058                     lightInfo->prev->next = lightInfo->next;
2059                     if (lightInfo->next != NULL) {
2060                         lightInfo->next->prev = lightInfo->prev;
2061                     }
2062
2063                     /* Add in at appropriate place (inbetween prev and pos) */
2064                     lightInfo->prev = prev;
2065                     lightInfo->next = pos;
2066                     if (prev == NULL) {
2067                         This->StateBlock->lights = lightInfo;
2068                     } else {
2069                         prev->next = lightInfo;
2070                     }
2071                     if (pos != NULL) {
2072                         pos->prev = lightInfo;
2073                     }
2074                 }
2075
2076                 /* Finally set up the light in gl itself */
2077                 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2078                 ENTER_GL();
2079                 setup_light(iface, glIndex, lightInfo);
2080                 glEnable(GL_LIGHT0 + glIndex);
2081                 checkGLcall("glEnable GL_LIGHT0 new setup");
2082                 LEAVE_GL();
2083                 
2084             }
2085         }
2086     }
2087     return D3D_OK;
2088 }
2089 HRESULT  WINAPI  IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2090
2091     PLIGHTINFOEL *lightInfo = NULL;
2092     ICOM_THIS(IDirect3DDevice8Impl,iface); 
2093     TRACE("(%p) : for idx(%ld)\n", This, Index);
2094     
2095     /* Locate the light in the live lights */
2096     lightInfo = This->StateBlock->lights;
2097     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2098
2099     if (lightInfo == NULL) {
2100         TRACE("Light enabled state requested but light not defined\n");
2101         return D3DERR_INVALIDCALL;
2102     }
2103     *pEnable = lightInfo->lightEnabled;
2104     return D3D_OK;
2105 }
2106 HRESULT  WINAPI  IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2107     ICOM_THIS(IDirect3DDevice8Impl,iface);
2108     TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2109
2110     /* Validate Index */
2111     if (Index >= GL_LIMITS(clipplanes)) {
2112         TRACE("Application has requested clipplane this device doesnt support\n");
2113         return D3DERR_INVALIDCALL;
2114     }
2115
2116     This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2117     This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2118     This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2119     This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2120     This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2121     This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2122
2123     /* Handle recording of state blocks */
2124     if (This->isRecordingState) {
2125         TRACE("Recording... not performing anything\n");
2126         return D3D_OK;
2127     }
2128
2129     /* Apply it */
2130
2131     ENTER_GL();
2132
2133     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2134     glMatrixMode(GL_MODELVIEW);
2135     glPushMatrix();
2136     glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2137
2138     TRACE("Clipplane [%f,%f,%f,%f]\n", 
2139           This->UpdateStateBlock->clipplane[Index][0], 
2140           This->UpdateStateBlock->clipplane[Index][1],
2141           This->UpdateStateBlock->clipplane[Index][2], 
2142           This->UpdateStateBlock->clipplane[Index][3]);
2143     glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2144     checkGLcall("glClipPlane");
2145
2146     glPopMatrix();
2147
2148     LEAVE_GL();
2149
2150     return D3D_OK;
2151 }
2152 HRESULT  WINAPI  IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2153     ICOM_THIS(IDirect3DDevice8Impl,iface);
2154     TRACE("(%p) : for idx %ld\n", This, Index);
2155
2156     /* Validate Index */
2157     if (Index >= GL_LIMITS(clipplanes)) {
2158         TRACE("Application has requested clipplane this device doesnt support\n");
2159         return D3DERR_INVALIDCALL;
2160     }
2161
2162     pPlane[0] = This->StateBlock->clipplane[Index][0];
2163     pPlane[1] = This->StateBlock->clipplane[Index][1];
2164     pPlane[2] = This->StateBlock->clipplane[Index][2];
2165     pPlane[3] = This->StateBlock->clipplane[Index][3];
2166     return D3D_OK;
2167 }
2168 HRESULT  WINAPI  IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2169     ICOM_THIS(IDirect3DDevice8Impl,iface);
2170     DWORD OldValue = This->StateBlock->renderstate[State];
2171         
2172     TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2173     This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2174     This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2175     This->UpdateStateBlock->renderstate[State] = Value;
2176
2177     /* Handle recording of state blocks */
2178     if (This->isRecordingState) {
2179         TRACE("Recording... not performing anything\n");
2180         return D3D_OK;
2181     }
2182
2183     ENTER_GL();
2184
2185     switch (State) {
2186     case D3DRS_FILLMODE                  :
2187         switch ((D3DFILLMODE) Value) {
2188         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2189         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2190         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2191         default:
2192             FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2193         }
2194         checkGLcall("glPolygonMode (fillmode)");
2195         break;
2196
2197     case D3DRS_LIGHTING                  :
2198         if (Value) {
2199             glEnable(GL_LIGHTING);
2200             checkGLcall("glEnable GL_LIGHTING");
2201         } else {
2202             glDisable(GL_LIGHTING);
2203             checkGLcall("glDisable GL_LIGHTING");
2204         }
2205         break;
2206
2207     case D3DRS_ZENABLE                   :
2208         switch ((D3DZBUFFERTYPE) Value) {
2209         case D3DZB_FALSE:
2210             glDisable(GL_DEPTH_TEST);
2211             checkGLcall("glDisable GL_DEPTH_TEST");
2212             break;
2213         case D3DZB_TRUE:
2214             glEnable(GL_DEPTH_TEST);
2215             checkGLcall("glEnable GL_DEPTH_TEST");
2216             break;
2217
2218         case D3DZB_USEW:
2219         default:
2220             FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2221         }
2222         break;
2223
2224     case D3DRS_CULLMODE                  :
2225
2226         /* If we are culling "back faces with clockwise vertices" then
2227            set front faces to be counter clockwise and enable culling  
2228            of back faces                                               */
2229         switch ((D3DCULL) Value) {
2230         case D3DCULL_NONE:
2231             glDisable(GL_CULL_FACE);
2232             checkGLcall("glDisable GL_CULL_FACE");
2233             break;
2234         case D3DCULL_CW:
2235             glEnable(GL_CULL_FACE);
2236             checkGLcall("glEnable GL_CULL_FACE");
2237             glFrontFace(GL_CCW);
2238             checkGLcall("glFrontFace GL_CCW");
2239             glCullFace(GL_BACK);
2240             break;
2241         case D3DCULL_CCW:
2242             glEnable(GL_CULL_FACE);
2243             checkGLcall("glEnable GL_CULL_FACE");
2244             glFrontFace(GL_CW); 
2245             checkGLcall("glFrontFace GL_CW");
2246             glCullFace(GL_BACK);
2247             break;
2248         default:
2249             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2250         }
2251         break;
2252
2253     case D3DRS_SHADEMODE                 :
2254         switch ((D3DSHADEMODE) Value) {
2255         case D3DSHADE_FLAT:
2256             glShadeModel(GL_FLAT);
2257             checkGLcall("glShadeModel");
2258             break;
2259         case D3DSHADE_GOURAUD:
2260             glShadeModel(GL_SMOOTH);
2261             checkGLcall("glShadeModel");
2262             break;
2263         case D3DSHADE_PHONG:
2264             FIXME("D3DSHADE_PHONG isnt supported?\n");
2265
2266             LEAVE_GL();
2267             return D3DERR_INVALIDCALL;
2268         default:
2269             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2270         }
2271         break;
2272
2273     case D3DRS_DITHERENABLE              :
2274         if (Value) {
2275             glEnable(GL_DITHER);
2276             checkGLcall("glEnable GL_DITHER");
2277         } else {
2278             glDisable(GL_DITHER);
2279             checkGLcall("glDisable GL_DITHER");
2280         }
2281         break;
2282
2283     case D3DRS_ZWRITEENABLE              :
2284         if (Value) {
2285             glDepthMask(1);
2286             checkGLcall("glDepthMask");
2287         } else {
2288             glDepthMask(0);
2289             checkGLcall("glDepthMask");
2290         }
2291         break;
2292
2293     case D3DRS_ZFUNC                     :
2294         {
2295             int glParm = GL_LESS;
2296
2297             switch ((D3DCMPFUNC) Value) {
2298             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2299             case D3DCMP_LESS:          glParm=GL_LESS; break;
2300             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2301             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2302             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2303             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2304             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2305             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2306             default:
2307                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2308             }
2309             glDepthFunc(glParm);
2310             checkGLcall("glDepthFunc");
2311         }
2312         break;
2313
2314     case D3DRS_AMBIENT                   :
2315         {
2316             float col[4];
2317             D3DCOLORTOGLFLOAT4(Value, col);
2318             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2319             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2320             checkGLcall("glLightModel for MODEL_AMBIENT");
2321
2322         }
2323         break;
2324
2325     case D3DRS_ALPHABLENDENABLE          :
2326         if (Value) {
2327             glEnable(GL_BLEND);
2328             checkGLcall("glEnable GL_BLEND");
2329         } else {
2330             glDisable(GL_BLEND);
2331             checkGLcall("glDisable GL_BLEND");
2332         };
2333         break;
2334
2335     case D3DRS_SRCBLEND                  :
2336     case D3DRS_DESTBLEND                 :
2337         {
2338             int newVal = GL_ZERO;
2339             switch (Value) {
2340             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
2341             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
2342             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
2343             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
2344             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
2345             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
2346             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
2347             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
2348             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
2349             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
2350             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
2351
2352             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
2353                 This->srcBlend = newVal;
2354                 This->dstBlend = newVal;
2355                 break;
2356
2357             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
2358                 This->srcBlend = newVal;
2359                 This->dstBlend = newVal;
2360                 break;
2361             default:
2362                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2363             }
2364
2365             if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2366             if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2367             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2368             glBlendFunc(This->srcBlend, This->dstBlend);
2369
2370             checkGLcall("glBlendFunc");
2371         }
2372         break;
2373
2374     case D3DRS_ALPHATESTENABLE           :
2375         if (Value) {
2376             glEnable(GL_ALPHA_TEST);
2377             checkGLcall("glEnable GL_ALPHA_TEST");
2378         } else {
2379             glDisable(GL_ALPHA_TEST);
2380             checkGLcall("glDisable GL_ALPHA_TEST");
2381         }
2382         break;
2383
2384     case D3DRS_ALPHAFUNC                 :
2385         {
2386             int glParm = GL_LESS;
2387             float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2388
2389             switch ((D3DCMPFUNC) Value) {
2390             case D3DCMP_NEVER:         glParm = GL_NEVER; break;
2391             case D3DCMP_LESS:          glParm = GL_LESS; break;
2392             case D3DCMP_EQUAL:         glParm = GL_EQUAL; break;
2393             case D3DCMP_LESSEQUAL:     glParm = GL_LEQUAL; break;
2394             case D3DCMP_GREATER:       glParm = GL_GREATER; break;
2395             case D3DCMP_NOTEQUAL:      glParm = GL_NOTEQUAL; break;
2396             case D3DCMP_GREATEREQUAL:  glParm = GL_GEQUAL; break;
2397             case D3DCMP_ALWAYS:        glParm = GL_ALWAYS; break;
2398             default:
2399                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2400             }
2401             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2402             glAlphaFunc(glParm, ref);
2403             This->alphafunc = glParm;
2404             checkGLcall("glAlphaFunc");
2405         }
2406         break;
2407
2408     case D3DRS_ALPHAREF                  :
2409         {
2410             int glParm = This->alphafunc;
2411             float ref = 1.0f;
2412
2413             ref = ((float) Value) / 255.0f;
2414             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2415             glAlphaFunc(glParm, ref);
2416             checkGLcall("glAlphaFunc");
2417         }
2418         break;
2419
2420     case D3DRS_CLIPPLANEENABLE           :
2421     case D3DRS_CLIPPING                  :
2422         {
2423             /* Ensure we only do the changed clip planes */
2424             DWORD enable  = 0xFFFFFFFF;
2425             DWORD disable = 0x00000000;
2426             
2427             /* If enabling / disabling all */
2428             if (State == D3DRS_CLIPPING) {
2429                 if (Value) {
2430                     enable  = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2431                     disable = 0x00;
2432                 } else {
2433                     disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2434                     enable  = 0x00;
2435                 }
2436             } else {
2437                 enable =   Value & ~OldValue;
2438                 disable = ~Value &  OldValue;
2439             }
2440             
2441             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
2442             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
2443             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
2444             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
2445             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
2446             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
2447             
2448             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2449             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2450             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2451             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2452             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2453             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2454         }
2455         break;
2456
2457     case D3DRS_BLENDOP                   :
2458         {
2459             int glParm = GL_FUNC_ADD;
2460
2461             switch ((D3DBLENDOP) Value) {
2462             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
2463             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
2464             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2465             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
2466             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
2467             default:
2468                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2469             }
2470             TRACE("glBlendEquation(%x)\n", glParm);
2471             glBlendEquation(glParm);
2472             checkGLcall("glBlendEquation");
2473         }
2474         break;
2475
2476     case D3DRS_TEXTUREFACTOR             :
2477         {
2478             int i;
2479
2480             /* Note the texture color applies to all textures whereas 
2481                GL_TEXTURE_ENV_COLOR applies to active only */
2482             float col[4];
2483             D3DCOLORTOGLFLOAT4(Value, col);
2484             /* Set the default alpha blend color */
2485             glBlendColor(col[0], col[1], col[2], col[3]);
2486             checkGLcall("glBlendColor");
2487
2488             /* And now the default texture color as well */
2489             for (i = 0; i < GL_LIMITS(textures); i++) {
2490
2491                 /* Note the D3DRS value applies to all textures, but GL has one
2492                    per texture, so apply it now ready to be used!               */
2493                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2494 #if defined(GL_VERSION_1_3)
2495                     glActiveTexture(GL_TEXTURE0 + i);
2496 #else
2497                     glActiveTextureARB(GL_TEXTURE0_ARB + i);
2498 #endif
2499                     checkGLcall("Activate texture.. to update const color");
2500                 } else if (i>0) {
2501                     FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2502                 }
2503
2504                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2505                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2506             }
2507         }
2508         break;
2509
2510     case D3DRS_SPECULARENABLE            : 
2511         {
2512             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2513                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2514                specular color. This is wrong:
2515                Separate specular color means the specular colour is maintained separately, whereas
2516                single color means it is merged in. However in both cases they are being used to
2517                some extent.
2518                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2519                NOTE: If not supported dont give FIXME as very minimal impact and very few people are
2520                   yet running 1.4!
2521              */
2522               if (Value) {
2523                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2524                 checkGLcall("glMaterialfv");
2525                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2526                   glEnable(GL_COLOR_SUM_EXT);
2527                 } else {
2528                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
2529                 }
2530                 checkGLcall("glEnable(GL_COLOR_SUM)");
2531               } else {
2532                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2533
2534                 /* for the case of enabled lighting: */
2535                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2536                 checkGLcall("glMaterialfv");
2537
2538                 /* for the case of disabled lighting: */
2539                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2540                   glDisable(GL_COLOR_SUM_EXT);
2541                 } else {
2542                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
2543                 }
2544                 checkGLcall("glDisable(GL_COLOR_SUM)");
2545               }
2546         }
2547         break;
2548
2549     case D3DRS_STENCILENABLE             :
2550         if (Value) {
2551             glEnable(GL_STENCIL_TEST);
2552             checkGLcall("glEnable GL_STENCIL_TEST");
2553         } else {
2554             glDisable(GL_STENCIL_TEST);
2555             checkGLcall("glDisable GL_STENCIL_TEST");
2556         }
2557         break;
2558
2559     case D3DRS_STENCILFUNC               :
2560         {
2561            int glParm = GL_ALWAYS;
2562            int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2563            GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2564
2565            switch ((D3DCMPFUNC) Value) {
2566            case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2567            case D3DCMP_LESS:          glParm=GL_LESS; break;
2568            case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2569            case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2570            case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2571            case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2572            case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2573            case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2574            default:
2575                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2576            }
2577            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2578            This->stencilfunc = glParm;
2579            glStencilFunc(glParm, ref, mask);
2580            checkGLcall("glStencilFunc");
2581         }
2582         break;
2583
2584     case D3DRS_STENCILREF                :
2585         {
2586            int glParm = This->stencilfunc;
2587            int ref = 0;
2588            GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2589
2590            ref = Value;
2591            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2592            glStencilFunc(glParm, ref, mask);
2593            checkGLcall("glStencilFunc");
2594         }
2595         break;
2596
2597     case D3DRS_STENCILMASK               :
2598         {
2599            int glParm = This->stencilfunc;
2600            int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2601            GLuint mask = Value;
2602
2603            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2604            glStencilFunc(glParm, ref, mask);
2605            checkGLcall("glStencilFunc");
2606         }
2607         break;
2608
2609     case D3DRS_STENCILFAIL               :
2610         {
2611             GLenum fail  ; 
2612             GLenum zpass ; 
2613             GLenum zfail ; 
2614
2615             fail = StencilOp(Value);
2616             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2617             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2618             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2619             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2620
2621             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2622             glStencilOp(fail, zfail, zpass);
2623             checkGLcall("glStencilOp(fail, zfail, zpass);");
2624         }
2625         break;
2626     case D3DRS_STENCILZFAIL              :
2627         {
2628             GLenum fail  ; 
2629             GLenum zpass ; 
2630             GLenum zfail ; 
2631
2632             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2633             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2634             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2635             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2636             zfail = StencilOp(Value);
2637
2638             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2639             glStencilOp(fail, zfail, zpass);
2640             checkGLcall("glStencilOp(fail, zfail, zpass);");
2641         }
2642         break;
2643     case D3DRS_STENCILPASS               :
2644         {
2645             GLenum fail  ; 
2646             GLenum zpass ; 
2647             GLenum zfail ; 
2648
2649             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2650             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2651             zpass = StencilOp(Value);
2652             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2653             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2654
2655             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2656             glStencilOp(fail, zfail, zpass);
2657             checkGLcall("glStencilOp(fail, zfail, zpass);");
2658         }
2659         break;
2660
2661     case D3DRS_STENCILWRITEMASK          :
2662         {
2663             glStencilMask(Value);
2664             TRACE("glStencilMask(%lu)\n", Value);
2665             checkGLcall("glStencilMask");
2666         }
2667         break;
2668
2669     case D3DRS_FOGENABLE                 :
2670         {
2671             if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2672                glEnable(GL_FOG);
2673                checkGLcall("glEnable GL_FOG");
2674             } else {
2675                glDisable(GL_FOG);
2676                checkGLcall("glDisable GL_FOG");
2677             }
2678         }
2679         break;
2680
2681     case D3DRS_FOGCOLOR                  :
2682         {
2683             float col[4];
2684             D3DCOLORTOGLFLOAT4(Value, col);
2685             /* Set the default alpha blend color */
2686             glFogfv(GL_FOG_COLOR, &col[0]);
2687             checkGLcall("glFog GL_FOG_COLOR");
2688         }
2689         break;
2690
2691     case D3DRS_FOGTABLEMODE              :
2692         {
2693           switch (Value) {
2694           case D3DFOG_NONE:    /* I don't know what to do here */ break;
2695           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2696           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2697           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2698           default:
2699             FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2700           }
2701         }
2702         break;
2703
2704     case D3DRS_FOGSTART                  :
2705         {
2706             float *f = (float*) &Value;
2707             glFogfv(GL_FOG_START, f);
2708             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2709             TRACE("Fog Start == %f\n", *f);
2710         }
2711         break;
2712
2713     case D3DRS_FOGEND                    :
2714         {
2715             float *f = (float*) &Value;
2716             glFogfv(GL_FOG_END, f);
2717             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2718             TRACE("Fog End == %f\n", *f);
2719         }
2720         break;
2721
2722     case D3DRS_FOGDENSITY                :
2723         {
2724             float *f = (float*) &Value;
2725             glFogfv(GL_FOG_DENSITY, f);
2726             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2727         }
2728         break;
2729
2730     case D3DRS_VERTEXBLEND               :
2731         {
2732           This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2733           TRACE("Vertex Blending state to %ld\n",  Value);
2734         }
2735         break;
2736
2737     case D3DRS_TWEENFACTOR               :
2738         {
2739           This->UpdateStateBlock->tween_factor = *((float*) &Value);
2740           TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2741         }
2742         break;
2743
2744     case D3DRS_INDEXEDVERTEXBLENDENABLE  :
2745         {
2746           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2747         }
2748         break;
2749
2750     case D3DRS_COLORVERTEX               :
2751     case D3DRS_DIFFUSEMATERIALSOURCE     :
2752     case D3DRS_SPECULARMATERIALSOURCE    :
2753     case D3DRS_AMBIENTMATERIALSOURCE     :
2754     case D3DRS_EMISSIVEMATERIALSOURCE    :
2755         {
2756             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2757
2758             if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2759                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2760                       This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2761                       This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2762                       This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2763                       This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2764
2765                 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2766                     if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2767                         Parm = GL_AMBIENT_AND_DIFFUSE;
2768                     } else {
2769                         Parm = GL_DIFFUSE;
2770                     }
2771                 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2772                     Parm = GL_AMBIENT;
2773                 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2774                     Parm = GL_EMISSION;
2775                 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2776                     Parm = GL_SPECULAR;
2777                 } else {
2778                     Parm = -1;
2779                 }
2780
2781                 if (Parm == -1) {
2782                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2783                 } else {
2784                     This->tracking_color = NEEDS_TRACKING;
2785                     This->tracking_parm  = Parm;
2786                 }
2787
2788             } else {
2789                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2790             }
2791         }
2792         break; 
2793
2794     case D3DRS_LINEPATTERN               :
2795         {
2796             D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2797             TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2798
2799             if (pattern->wRepeatFactor) {
2800                 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2801                 checkGLcall("glLineStipple(repeat, linepattern)");
2802                 glEnable(GL_LINE_STIPPLE);
2803                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2804             } else {
2805                 glDisable(GL_LINE_STIPPLE);
2806                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2807             }
2808         }
2809         break;
2810
2811     case D3DRS_ZBIAS                     :
2812         {
2813             if (Value) {
2814                 TRACE("ZBias value %f\n", *((float*)&Value));
2815                 glPolygonOffset(0, -*((float*)&Value));
2816                 checkGLcall("glPolygonOffset(0, -Value)");
2817                 glEnable(GL_POLYGON_OFFSET_FILL);
2818                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2819                 glEnable(GL_POLYGON_OFFSET_LINE);
2820                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2821                 glEnable(GL_POLYGON_OFFSET_POINT);
2822                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2823             } else {
2824                 glDisable(GL_POLYGON_OFFSET_FILL);
2825                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2826                 glDisable(GL_POLYGON_OFFSET_LINE);
2827                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2828                 glDisable(GL_POLYGON_OFFSET_POINT);
2829                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2830             }
2831         }
2832         break;
2833
2834     case D3DRS_NORMALIZENORMALS          :
2835         if (Value) {
2836             glEnable(GL_NORMALIZE);
2837             checkGLcall("glEnable(GL_NORMALIZE);");
2838         } else {
2839             glDisable(GL_NORMALIZE);
2840             checkGLcall("glDisable(GL_NORMALIZE);");
2841         }
2842         break;
2843
2844     case D3DRS_POINTSIZE                 :
2845         TRACE("Set point size to %f\n", *((float*)&Value));
2846         glPointSize(*((float*)&Value));
2847         checkGLcall("glPointSize(...);");
2848         break;
2849
2850     case D3DRS_POINTSIZE_MIN             :
2851         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2852           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2853           checkGLcall("glPointParameterfEXT(...);");
2854         } else {
2855           FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2856         }
2857         break;
2858
2859     case D3DRS_POINTSIZE_MAX             :
2860         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2861           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2862           checkGLcall("glPointParameterfEXT(...);");
2863         } else {
2864           FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2865         }
2866         break;
2867
2868     case D3DRS_POINTSCALE_A              :
2869     case D3DRS_POINTSCALE_B              :
2870     case D3DRS_POINTSCALE_C              :
2871     case D3DRS_POINTSCALEENABLE          :
2872         {
2873             /* If enabled, supply the parameters, otherwise fall back to defaults */
2874             if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2875                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2876                 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2877                 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2878                 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2879
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 on this opengl\n");
2885                 }
2886             } else {
2887                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2888                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2889                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2890                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2891                 } else {
2892                   TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2893                 }
2894             }
2895             break;
2896         }
2897
2898     case D3DRS_COLORWRITEENABLE          :
2899         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n", 
2900               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
2901               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2902               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
2903               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0); 
2904         glColorMask(Value & D3DCOLORWRITEENABLE_RED, 
2905                     Value & D3DCOLORWRITEENABLE_GREEN,
2906                     Value & D3DCOLORWRITEENABLE_BLUE, 
2907                     Value & D3DCOLORWRITEENABLE_ALPHA);
2908         checkGLcall("glColorMask(...)");
2909                 break;
2910
2911         /* Unhandled yet...! */
2912     case D3DRS_LASTPIXEL                 :
2913     case D3DRS_ZVISIBLE                  :
2914     case D3DRS_EDGEANTIALIAS             :
2915     case D3DRS_RANGEFOGENABLE            :
2916     case D3DRS_WRAP0                     :
2917     case D3DRS_WRAP1                     :
2918     case D3DRS_WRAP2                     :
2919     case D3DRS_WRAP3                     :
2920     case D3DRS_WRAP4                     :
2921     case D3DRS_WRAP5                     :
2922     case D3DRS_WRAP6                     :
2923     case D3DRS_WRAP7                     :
2924     case D3DRS_FOGVERTEXMODE             :
2925     case D3DRS_LOCALVIEWER               :
2926     case D3DRS_SOFTWAREVERTEXPROCESSING  :
2927     case D3DRS_POINTSPRITEENABLE         :
2928     case D3DRS_MULTISAMPLEANTIALIAS      :
2929     case D3DRS_MULTISAMPLEMASK           :
2930     case D3DRS_PATCHEDGESTYLE            :
2931     case D3DRS_PATCHSEGMENTS             :
2932     case D3DRS_DEBUGMONITORTOKEN         :
2933     case D3DRS_POSITIONORDER             :
2934     case D3DRS_NORMALORDER               :
2935         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2936         TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2937         break;
2938     default:
2939         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2940     }
2941
2942     LEAVE_GL();
2943
2944     return D3D_OK;
2945 }
2946 HRESULT  WINAPI  IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2947     ICOM_THIS(IDirect3DDevice8Impl,iface);
2948     TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2949     *pValue = This->StateBlock->renderstate[State];
2950     return D3D_OK;
2951 }
2952 HRESULT  WINAPI  IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2953   ICOM_THIS(IDirect3DDevice8Impl,iface);
2954   
2955   TRACE("(%p)\n", This);
2956   
2957   return IDirect3DDeviceImpl_BeginStateBlock(This);
2958 }
2959 HRESULT  WINAPI  IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2960   IDirect3DStateBlockImpl* pSB;
2961   ICOM_THIS(IDirect3DDevice8Impl,iface);
2962   HRESULT res;
2963
2964   TRACE("(%p)\n", This);
2965
2966   res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2967   *pToken = (DWORD) pSB;
2968   return res;
2969 }
2970
2971 HRESULT  WINAPI  IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2972   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2973   ICOM_THIS(IDirect3DDevice8Impl,iface);
2974
2975   TRACE("(%p)\n", This);
2976
2977   return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2978
2979 }
2980 HRESULT  WINAPI  IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2981   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2982   ICOM_THIS(IDirect3DDevice8Impl,iface);
2983
2984   TRACE("(%p)\n", This);
2985
2986   return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2987 }
2988 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2989   IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2990   ICOM_THIS(IDirect3DDevice8Impl,iface);
2991
2992   TRACE("(%p)\n", This);
2993
2994   return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
2995 }
2996
2997 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
2998   IDirect3DStateBlockImpl* pSB;
2999   ICOM_THIS(IDirect3DDevice8Impl,iface);
3000   HRESULT res;
3001
3002   TRACE("(%p) : for type %d\n", This, Type);
3003
3004   res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3005   *pToken = (DWORD) pSB;
3006   return res;
3007 }
3008
3009 HRESULT  WINAPI  IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3010     ICOM_THIS(IDirect3DDevice8Impl,iface);
3011     FIXME("(%p) : stub\n", This);    return D3D_OK;
3012 }
3013 HRESULT  WINAPI  IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3014     ICOM_THIS(IDirect3DDevice8Impl,iface);
3015     FIXME("(%p) : stub\n", This);    return D3D_OK;
3016 }
3017 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3018     ICOM_THIS(IDirect3DDevice8Impl,iface);
3019     TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3020     *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3021     IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3022     return D3D_OK;
3023 }
3024 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3025
3026     IDirect3DBaseTexture8 *oldTxt;
3027     BOOL reapplyStates = TRUE;
3028     DWORD oldTextureDimensions = -1;
3029     DWORD reapplyFlags = 0;
3030
3031     ICOM_THIS(IDirect3DDevice8Impl,iface);
3032     D3DRESOURCETYPE textureType;
3033
3034     oldTxt = This->UpdateStateBlock->textures[Stage];
3035     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3036
3037     /* Reject invalid texture units */
3038     if (Stage >= GL_LIMITS(textures)) {
3039         TRACE("Attempt to access invalid texture rejected\n");
3040         return D3DERR_INVALIDCALL;
3041     }
3042
3043     This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3044     This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3045     This->UpdateStateBlock->textures[Stage] = pTexture;
3046
3047     /* Handle recording of state blocks */
3048     if (This->isRecordingState) {
3049         TRACE("Recording... not performing anything\n");
3050         return D3D_OK;
3051     }
3052
3053     oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3054     ENTER_GL();
3055
3056     /* Make appropriate texture active */
3057     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3058 #if defined(GL_VERSION_1_3)
3059         glActiveTexture(GL_TEXTURE0 + Stage);
3060 #else
3061         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3062 #endif
3063         checkGLcall("glActiveTextureARB");
3064     } else if (Stage>0) {
3065         FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3066     }
3067
3068     /* Decrement the count of the previous texture */
3069     if (NULL != oldTxt) {
3070         IDirect3DBaseTexture8Impl_Release(oldTxt);
3071     }
3072
3073     if (NULL != pTexture) {
3074         IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3075
3076         /* Now setup the texture appropraitly */
3077         textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3078
3079         if (textureType == D3DRTYPE_TEXTURE) {
3080           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3081             TRACE("Skipping setting texture as old == new\n");
3082             reapplyStates = FALSE;
3083           } else {
3084             /* Standard 2D texture */
3085             TRACE("Standard 2d texture\n");
3086             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3087
3088             /* Load up the texture now */
3089             IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3090           }
3091         } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3092           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3093             TRACE("Skipping setting texture as old == new\n");
3094             reapplyStates = FALSE;
3095           } else {
3096             /* Standard 3D (volume) texture */
3097             TRACE("Standard 3d texture\n");
3098             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3099
3100             /* Load up the texture now */
3101             IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3102           }
3103         } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3104           if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3105             TRACE("Skipping setting texture as old == new\n");
3106             reapplyStates = FALSE;
3107           } else {
3108             /* Standard Cube texture */
3109             TRACE("Standard Cube texture\n");
3110             This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3111
3112             /* Load up the texture now */
3113             IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3114           }
3115         } else {
3116             FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3117         }
3118     } else {
3119         TRACE("Setting to no texture (ie default texture)\n");
3120         This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3121         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3122         checkGLcall("glBindTexture");
3123         TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3124     }
3125
3126     /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3127     if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3128        glDisable(oldTextureDimensions);
3129        checkGLcall("Disable oldTextureDimensions");
3130        if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3131           glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3132           checkGLcall("glEnable new texture dimensions");
3133        }
3134
3135        /* If Alpha arg1 is texture then handle the special case when there changes between a
3136           texture and no texture - See comments in set_tex_op                                  */
3137        if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) && 
3138            (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3139        {
3140            reapplyFlags |= REAPPLY_ALPHAOP;
3141        }
3142     }
3143
3144
3145     /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3146        a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3147     if (reapplyStates) {
3148        setupTextureStates(iface, Stage, reapplyFlags);
3149     }
3150
3151     LEAVE_GL();   
3152
3153     return D3D_OK;
3154 }
3155
3156 HRESULT  WINAPI  IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3157     ICOM_THIS(IDirect3DDevice8Impl,iface);
3158     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3159     *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3160     return D3D_OK;
3161 }
3162
3163 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3164     ICOM_THIS(IDirect3DDevice8Impl,iface);
3165
3166     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3167    
3168     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3169
3170     /* Reject invalid texture units */
3171     if (Stage >= GL_LIMITS(textures)) {
3172         TRACE("Attempt to access invalid texture rejected\n");
3173         return D3DERR_INVALIDCALL;
3174     }
3175
3176     This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3177     This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3178     This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3179
3180     /* Handle recording of state blocks */
3181     if (This->isRecordingState) {
3182         TRACE("Recording... not performing anything\n");
3183         return D3D_OK;
3184     }
3185
3186     ENTER_GL();
3187
3188     /* Make appropriate texture active */
3189     VTRACE(("Activating appropriate texture state %ld\n", Stage));
3190     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3191 #if defined(GL_VERSION_1_3)
3192         glActiveTexture(GL_TEXTURE0 + Stage);
3193         vcheckGLcall("glActiveTexture");
3194 #else
3195         glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3196         vcheckGLcall("glActiveTextureARB");
3197 #endif
3198     } else if (Stage > 0) {
3199         FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3200     }
3201
3202     switch (Type) {
3203
3204     case D3DTSS_MINFILTER             :
3205     case D3DTSS_MIPFILTER             :
3206         {
3207             DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3208             DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3209             GLint realVal = GL_LINEAR;
3210
3211             if (ValueMIN == D3DTEXF_POINT) {
3212                 /* GL_NEAREST_* */
3213                 if (ValueMIP == D3DTEXF_POINT) {
3214                     realVal = GL_NEAREST_MIPMAP_NEAREST;
3215                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3216                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3217                 } else if (ValueMIP == D3DTEXF_NONE) {
3218                     realVal = GL_NEAREST;
3219                 } else {
3220                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3221                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3222                 }
3223             } else if (ValueMIN == D3DTEXF_LINEAR) {
3224                 /* GL_LINEAR_* */
3225                 if (ValueMIP == D3DTEXF_POINT) {
3226                     realVal = GL_LINEAR_MIPMAP_NEAREST;
3227                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3228                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3229                 } else if (ValueMIP == D3DTEXF_NONE) {
3230                     realVal = GL_LINEAR;
3231                 } else {
3232                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3233                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3234                 }
3235             } else if (ValueMIN == D3DTEXF_NONE) {
3236                 /* Doesnt really make sense - Windows just seems to disable
3237                    mipmapping when this occurs                              */
3238                 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3239                 realVal = GL_LINEAR;
3240
3241             } else {
3242                 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3243                 realVal = GL_LINEAR_MIPMAP_LINEAR;
3244             }
3245
3246             TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3247             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3248             checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3249         }
3250         break;
3251
3252     case D3DTSS_MAXANISOTROPY         :
3253       { 
3254         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3255           glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3256           checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3257         }
3258       }
3259       break;
3260
3261     case D3DTSS_MAGFILTER             :
3262         if (Value == D3DTEXF_POINT) {
3263             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3264             checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3265         } else if (Value == D3DTEXF_LINEAR) {
3266             glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3267             checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3268         } else {
3269             FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3270         }
3271         break;
3272
3273     case D3DTSS_ALPHAOP               :
3274     case D3DTSS_COLOROP               :
3275         {
3276
3277             if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3278                 /* TODO: Disable by making this and all later levels disabled */
3279                 glDisable(GL_TEXTURE_1D);
3280                 checkGLcall("Disable GL_TEXTURE_1D");
3281                 glDisable(GL_TEXTURE_2D);
3282                 checkGLcall("Disable GL_TEXTURE_2D");
3283                 glDisable(GL_TEXTURE_3D);
3284                 checkGLcall("Disable GL_TEXTURE_3D");
3285                 break; /* Dont bother setting the texture operations */
3286             } else {
3287                 /* Enable only the appropriate texture dimension */
3288                 if (Type == D3DTSS_COLOROP) {
3289                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3290                         glEnable(GL_TEXTURE_1D);
3291                         checkGLcall("Enable GL_TEXTURE_1D");
3292                     } else {
3293                         glDisable(GL_TEXTURE_1D);
3294                         checkGLcall("Disable GL_TEXTURE_1D");
3295                     } 
3296                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3297                         glEnable(GL_TEXTURE_2D);
3298                         checkGLcall("Enable GL_TEXTURE_2D");
3299                     } else {
3300                         glDisable(GL_TEXTURE_2D);
3301                         checkGLcall("Disable GL_TEXTURE_2D");
3302                     }
3303                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3304                         glEnable(GL_TEXTURE_3D);
3305                         checkGLcall("Enable GL_TEXTURE_3D");
3306                     } else {
3307                         glDisable(GL_TEXTURE_3D);
3308                         checkGLcall("Disable GL_TEXTURE_3D");
3309                     }
3310                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3311                         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3312                         checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3313                     } else {
3314                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3315                         checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3316                     }
3317                 }
3318             }
3319             /* Drop through... (Except disable case) */
3320         case D3DTSS_COLORARG0             :
3321         case D3DTSS_COLORARG1             :
3322         case D3DTSS_COLORARG2             :
3323         case D3DTSS_ALPHAARG0             :
3324         case D3DTSS_ALPHAARG1             :
3325         case D3DTSS_ALPHAARG2             :
3326             {
3327                 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 || 
3328                                    Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3329                 if (isAlphaArg) {
3330                     set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3331                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1], 
3332                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2], 
3333                                This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3334                 } else {
3335                     set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3336                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1], 
3337                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2], 
3338                                This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3339                 }
3340             }
3341             break;
3342         }
3343
3344     case D3DTSS_ADDRESSU              :
3345     case D3DTSS_ADDRESSV              :
3346     case D3DTSS_ADDRESSW              :
3347         {
3348             GLint wrapParm = GL_REPEAT;
3349             switch (Value) {
3350             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
3351             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;      
3352             case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break;      /* FIXME: Not right, but better */
3353 #if defined(GL_VERSION_1_4)
3354             case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3355 #elif defined(GL_ARB_texture_mirrored_repeat)
3356             case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3357 #else
3358             case D3DTADDRESS_MIRROR:      /* Unsupported in OpenGL pre-1.4 */
3359 #endif
3360             case D3DTADDRESS_MIRRORONCE:  /* Unsupported in OpenGL         */
3361             default:
3362                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3363                 wrapParm = GL_REPEAT; 
3364             }
3365
3366             switch (Type) {
3367             case D3DTSS_ADDRESSU:
3368                 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3369                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3370                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3371                 break;
3372             case D3DTSS_ADDRESSV:
3373                 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3374                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3375                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3376                 break;
3377             case D3DTSS_ADDRESSW:
3378                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3379                 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3380                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3381                 break;
3382             default: /* nop */
3383                 break; /** stupic compilator */
3384             }
3385         }
3386         break;
3387
3388     case D3DTSS_BORDERCOLOR           :
3389         {
3390             float col[4];
3391             D3DCOLORTOGLFLOAT4(Value, col);
3392             TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value); 
3393             glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3394             checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3395         }
3396         break;
3397
3398     case D3DTSS_TEXCOORDINDEX         :
3399         {
3400             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3401
3402             /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include 
3403                   one flag, you can still specify an index value, which the system uses to 
3404                   determine the texture wrapping mode.  
3405                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3406                   means use the vertex position (camera-space) as the input texture coordinates 
3407                   for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render 
3408                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3409                   to the TEXCOORDINDEX value */
3410           
3411             /** 
3412              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos 
3413              */
3414             switch (Value & 0xFFFF0000) {
3415             case D3DTSS_TCI_PASSTHRU:
3416               /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3417               glDisable(GL_TEXTURE_GEN_S);
3418               glDisable(GL_TEXTURE_GEN_T);
3419               glDisable(GL_TEXTURE_GEN_R);
3420               checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3421               break;
3422
3423             case D3DTSS_TCI_CAMERASPACEPOSITION:
3424               /* CameraSpacePosition means use the vertex position, transformed to camera space, 
3425                  as the input texture coordinates for this stage's texture transformation. This 
3426                  equates roughly to EYE_LINEAR                                                  */
3427               {
3428                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3429                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3430                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3431                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3432                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3433
3434                 glMatrixMode(GL_MODELVIEW);
3435                 glPushMatrix();
3436                 glLoadIdentity();
3437                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3438                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3439                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3440                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3441                 glPopMatrix();
3442                 
3443                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3444                 glEnable(GL_TEXTURE_GEN_S);
3445                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3446                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3447                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3448                 glEnable(GL_TEXTURE_GEN_T);
3449                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3450                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3451                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3452                 glEnable(GL_TEXTURE_GEN_R);
3453                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3454                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3455                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3456               }
3457               break;
3458
3459 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3460             case D3DTSS_TCI_CAMERASPACENORMAL:
3461               {
3462                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3463                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3464                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3465                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3466                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3467
3468                 glMatrixMode(GL_MODELVIEW);
3469                 glPushMatrix();
3470                 glLoadIdentity();
3471                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3472                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3473                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3474                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3475                 glPopMatrix();
3476
3477                 glEnable(GL_TEXTURE_GEN_S);
3478                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3479                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3480                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3481                 glEnable(GL_TEXTURE_GEN_T);
3482                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3483                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3484                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3485                 glEnable(GL_TEXTURE_GEN_R);
3486                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3487                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3488                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3489               }
3490               break;
3491 #endif
3492
3493 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3494             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3495               {
3496
3497                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3498                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3499                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3500                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3501                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3502
3503                 glMatrixMode(GL_MODELVIEW);
3504                 glPushMatrix();
3505                 glLoadIdentity();
3506                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3507                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3508                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3509                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3510                 glPopMatrix();
3511                 
3512                 glEnable(GL_TEXTURE_GEN_S);
3513                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3514                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3515                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3516                 glEnable(GL_TEXTURE_GEN_T);
3517                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3518                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3519                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3520                 glEnable(GL_TEXTURE_GEN_R);
3521                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3522                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3523                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3524               }
3525               break;
3526 #endif
3527
3528             /* Unhandled types: */
3529             default:
3530                 /* Todo: */
3531                 /* ? disable GL_TEXTURE_GEN_n ? */ 
3532                 glDisable(GL_TEXTURE_GEN_S);
3533                 glDisable(GL_TEXTURE_GEN_T);
3534                 glDisable(GL_TEXTURE_GEN_R);
3535                 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3536                 break;
3537             }
3538         }
3539         break;
3540
3541         /* Unhandled */
3542     case D3DTSS_BUMPENVMAT00          :
3543     case D3DTSS_BUMPENVMAT01          :
3544         TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3545         break;
3546     case D3DTSS_BUMPENVMAT10          :
3547     case D3DTSS_BUMPENVMAT11          :
3548         TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3549         break;
3550
3551     case D3DTSS_TEXTURETRANSFORMFLAGS :
3552         set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3553         break; 
3554
3555     case D3DTSS_MIPMAPLODBIAS         :
3556     case D3DTSS_MAXMIPLEVEL           :
3557     case D3DTSS_BUMPENVLSCALE         :
3558     case D3DTSS_BUMPENVLOFFSET        :
3559     case D3DTSS_RESULTARG             :
3560     default:
3561         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3562         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3563     }
3564
3565     LEAVE_GL();
3566
3567     return D3D_OK;
3568 }
3569 HRESULT  WINAPI  IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3570     ICOM_THIS(IDirect3DDevice8Impl,iface);
3571     TRACE("(%p) : stub\n", This);    /* FIXME: Needs doing, but called often and is harmless */
3572     return D3D_OK;
3573 }
3574 HRESULT  WINAPI  IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3575     ICOM_THIS(IDirect3DDevice8Impl,iface);
3576     FIXME("(%p) : stub\n", This);    
3577     return D3D_OK;
3578 }
3579 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3580     ICOM_THIS(IDirect3DDevice8Impl,iface);
3581     FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3582           pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3583     memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3584     return D3D_OK;
3585 }
3586 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3587     ICOM_THIS(IDirect3DDevice8Impl,iface);
3588     memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3589     FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3590           pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3591     return D3D_OK;
3592 }
3593 HRESULT  WINAPI  IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3594     ICOM_THIS(IDirect3DDevice8Impl,iface);
3595     FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3596     This->currentPalette = PaletteNumber;
3597
3598 #if defined(GL_EXT_paletted_texture)
3599     if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3600
3601       ENTER_GL();
3602
3603       GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D,    /* target */
3604                                   GL_RGBA,          /* internal format */
3605                                   256,              /* table size */
3606                                   GL_RGBA,          /* table format */
3607                                   GL_UNSIGNED_BYTE, /* table type */
3608                                   This->palettes[PaletteNumber]);
3609       checkGLcall("glColorTableEXT");
3610
3611       LEAVE_GL();
3612
3613     } else {
3614       /* Delayed palette handling ... waiting for software emulation into preload code */
3615     }
3616 #endif
3617     return D3D_OK;
3618 }
3619 HRESULT  WINAPI  IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3620     ICOM_THIS(IDirect3DDevice8Impl,iface);
3621     *PaletteNumber = This->currentPalette;
3622     FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3623     return D3D_OK;
3624 }
3625 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3626
3627     ICOM_THIS(IDirect3DDevice8Impl,iface);
3628     This->StateBlock->streamIsUP = FALSE;
3629
3630     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3631     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3632
3633     return D3D_OK;
3634 }
3635 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3636                                                            UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3637     UINT idxStride = 2;
3638     IDirect3DIndexBuffer8      *pIB;
3639     D3DINDEXBUFFER_DESC         IdxBufDsc;
3640
3641     ICOM_THIS(IDirect3DDevice8Impl,iface);
3642     pIB = This->StateBlock->pIndexData;
3643     This->StateBlock->streamIsUP = FALSE;
3644
3645     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, 
3646           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3647           minIndex, NumVertices, startIndex, primCount);
3648
3649     IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3650     if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3651         idxStride = 2;
3652     } else {
3653         idxStride = 4;
3654     }
3655
3656     drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3657                    minIndex);
3658
3659     return D3D_OK;
3660 }
3661 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3662     ICOM_THIS(IDirect3DDevice8Impl,iface);
3663
3664     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), 
3665           PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3666
3667     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3668
3669     /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3670     This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData; 
3671     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3672     This->StateBlock->streamIsUP = TRUE;
3673     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3674     This->StateBlock->stream_stride[0] = 0;
3675     This->StateBlock->stream_source[0] = NULL;
3676
3677     /*stream zero settings set to null at end */
3678     return D3D_OK;
3679 }
3680 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3681                                                              UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3682                                                              D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3683                                                              UINT VertexStreamZeroStride) {
3684     int idxStride;
3685     ICOM_THIS(IDirect3DDevice8Impl,iface);
3686     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),
3687           MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,  IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3688
3689     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3690     if (IndexDataFormat == D3DFMT_INDEX16) {
3691         idxStride = 2;
3692     } else {
3693         idxStride = 4;
3694     }
3695
3696     /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3697     This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3698     This->StateBlock->streamIsUP = TRUE;
3699     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3700     drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3701
3702     /*stream zero settings set to null at end */
3703     This->StateBlock->stream_source[0] = NULL;
3704     This->StateBlock->stream_stride[0] = 0;
3705     IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3706
3707     return D3D_OK;
3708 }
3709 HRESULT  WINAPI  IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3710     ICOM_THIS(IDirect3DDevice8Impl,iface);
3711     FIXME("(%p) : stub\n", This);    return D3D_OK;
3712 }
3713 HRESULT  WINAPI  IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3714     ICOM_THIS(IDirect3DDevice8Impl,iface);
3715     IDirect3DVertexShaderImpl* object;
3716     IDirect3DVertexShaderDeclarationImpl* attached_decl;
3717     HRESULT res;
3718     UINT i;
3719
3720     TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3721     if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3722       return D3DERR_INVALIDCALL;
3723     }
3724     for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3725     if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3726       return D3DERR_OUTOFVIDEOMEMORY;
3727     }
3728
3729     /** Create the Vertex Shader */
3730     res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3731     /** TODO: check FAILED(res) */
3732
3733     /** Create and Bind the Vertex Shader Declaration */
3734     res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3735     /** TODO: check FAILED(res) */
3736
3737     VertexShaders[i] = object;
3738     VertexShaderDeclarations[i] = attached_decl;
3739     *pHandle = VS_HIGHESTFIXEDFXF + i;
3740     TRACE("Finished creating vertex shader %lx\n", *pHandle);
3741
3742     return D3D_OK;
3743 }
3744 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3745     ICOM_THIS(IDirect3DDevice8Impl,iface);
3746
3747     This->UpdateStateBlock->VertexShader = Handle;
3748     This->UpdateStateBlock->Changed.vertexShader = TRUE;
3749     This->UpdateStateBlock->Set.vertexShader = TRUE;
3750     
3751     if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3752       TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3753       This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3754       This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3755       This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3756     } else { /* use a fvf, so desactivate the vshader decl */
3757       TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3758       This->UpdateStateBlock->vertexShaderDecl = NULL;
3759       This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3760       This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3761     }
3762     /* Handle recording of state blocks */
3763     if (This->isRecordingState) {
3764       TRACE("Recording... not performing anything\n");
3765       return D3D_OK;
3766     }
3767     /**
3768      * TODO: merge HAL shaders context switching from prototype
3769      */
3770     return D3D_OK;
3771 }
3772 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3773     ICOM_THIS(IDirect3DDevice8Impl,iface);
3774     TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3775     *pHandle = This->StateBlock->VertexShader;
3776     return D3D_OK;
3777 }
3778
3779 HRESULT  WINAPI  IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3780     ICOM_THIS(IDirect3DDevice8Impl,iface);
3781     IDirect3DVertexShaderImpl* object; 
3782     IDirect3DVertexShaderDeclarationImpl* attached_decl;
3783
3784     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3785       return D3DERR_INVALIDCALL;
3786     }
3787
3788     /**
3789      * Delete Vertex Shader
3790      */
3791     object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3792     if (NULL == object) {
3793       return D3DERR_INVALIDCALL;
3794     }
3795     TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3796     /* TODO: check validity of object */
3797     if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3798     HeapFree(GetProcessHeap(), 0, (void *)object->data);
3799     HeapFree(GetProcessHeap(), 0, (void *)object);
3800     VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3801
3802     /**
3803      * Delete Vertex Shader Declaration
3804      */
3805     attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3806     if (NULL == attached_decl) {
3807       return D3DERR_INVALIDCALL;
3808     } 
3809     TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3810     /* TODO: check validity of object */
3811     HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3812     HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3813     VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3814
3815     return D3D_OK;
3816 }
3817
3818 HRESULT  WINAPI  IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3819   ICOM_THIS(IDirect3DDevice8Impl,iface);
3820
3821   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3822     ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3823     return D3DERR_INVALIDCALL;
3824   }
3825   if (NULL == pConstantData) {
3826     return D3DERR_INVALIDCALL;
3827   }
3828   if (ConstantCount > 1) {
3829     FLOAT* f = (FLOAT*)pConstantData;
3830     UINT i;
3831     TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3832     for (i = 0; i < ConstantCount; ++i) {
3833       TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3834       f += 4;
3835     }
3836   } else { 
3837     FLOAT* f = (FLOAT*) pConstantData;
3838     TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3839   }
3840   This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3841   memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3842   return D3D_OK;
3843 }
3844 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3845   ICOM_THIS(IDirect3DDevice8Impl,iface);
3846
3847   TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3848   if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3849     return D3DERR_INVALIDCALL;
3850   }
3851   if (NULL == pConstantData) {
3852     return D3DERR_INVALIDCALL;
3853   }
3854   memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3855   return D3D_OK;
3856 }
3857 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3858   /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3859   IDirect3DVertexShaderDeclarationImpl* attached_decl;
3860   
3861   attached_decl = VERTEX_SHADER_DECL(Handle);
3862   if (NULL == attached_decl) {
3863     return D3DERR_INVALIDCALL;
3864   }
3865   return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3866 }
3867 HRESULT  WINAPI  IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3868   /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3869   IDirect3DVertexShaderImpl* object;
3870   
3871   object = VERTEX_SHADER(Handle);
3872   if (NULL == object) {
3873     return D3DERR_INVALIDCALL;
3874   }
3875   return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3876 }
3877
3878 HRESULT  WINAPI  IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3879     ICOM_THIS(IDirect3DDevice8Impl,iface);
3880     IDirect3DIndexBuffer8 *oldIdxs;
3881
3882     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3883     oldIdxs = This->StateBlock->pIndexData;
3884
3885     This->UpdateStateBlock->Changed.Indices = TRUE;
3886     This->UpdateStateBlock->Set.Indices = TRUE;
3887     This->UpdateStateBlock->pIndexData = pIndexData;
3888     This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3889
3890     /* Handle recording of state blocks */
3891     if (This->isRecordingState) {
3892         TRACE("Recording... not performing anything\n");
3893         return D3D_OK;
3894     }
3895
3896     if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3897     if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3898     return D3D_OK;
3899 }
3900 HRESULT  WINAPI  IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3901     ICOM_THIS(IDirect3DDevice8Impl,iface);
3902     FIXME("(%p) : stub\n", This);
3903
3904     *ppIndexData = This->StateBlock->pIndexData;
3905     /* up ref count on ppindexdata */
3906     if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3907     *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3908
3909     return D3D_OK;
3910 }
3911 HRESULT  WINAPI  IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3912     ICOM_THIS(IDirect3DDevice8Impl,iface);
3913     IDirect3DPixelShaderImpl* object;
3914     HRESULT res;
3915     UINT i;
3916
3917     TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3918     if (NULL == pFunction || NULL == pHandle) {
3919       return D3DERR_INVALIDCALL;
3920     }
3921     for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3922     if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3923       return D3DERR_OUTOFVIDEOMEMORY;
3924     }
3925
3926     /** Create the Pixel Shader */
3927     res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3928     if (SUCCEEDED(res)) {
3929       PixelShaders[i] = object;
3930       *pHandle = VS_HIGHESTFIXEDFXF + i;
3931       return D3D_OK;
3932     } 
3933     *pHandle = 0xFFFFFFFF;
3934     return res;
3935 }
3936 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3937     ICOM_THIS(IDirect3DDevice8Impl,iface);
3938
3939     This->UpdateStateBlock->PixelShader = Handle;
3940     This->UpdateStateBlock->Changed.pixelShader = TRUE;
3941     This->UpdateStateBlock->Set.pixelShader = TRUE;
3942
3943     /* Handle recording of state blocks */
3944     if (This->isRecordingState) {
3945         TRACE_(d3d_shader)("Recording... not performing anything\n");
3946         return D3D_OK;
3947     }
3948
3949     /* FIXME: Quieten when not being used */
3950     if (Handle != 0) {
3951       FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3952     } else {
3953       TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3954     }
3955
3956     return D3D_OK;
3957 }
3958 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3959     ICOM_THIS(IDirect3DDevice8Impl,iface);
3960     TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3961     *pHandle = This->StateBlock->PixelShader;
3962     return D3D_OK;
3963 }
3964
3965 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3966     ICOM_THIS(IDirect3DDevice8Impl,iface);
3967     IDirect3DPixelShaderImpl* object;   
3968
3969     if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3970       return D3DERR_INVALIDCALL;
3971     }
3972     object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3973     TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3974     /* TODO: check validity of object before free */
3975     if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3976     HeapFree(GetProcessHeap(), 0, (void *)object->data);
3977     HeapFree(GetProcessHeap(), 0, (void *)object);
3978     PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3979
3980     return D3D_OK;
3981 }
3982
3983 HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3984   ICOM_THIS(IDirect3DDevice8Impl,iface);
3985
3986   if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3987     ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
3988     return D3DERR_INVALIDCALL;
3989   }
3990   if (NULL == pConstantData) {
3991     return D3DERR_INVALIDCALL;
3992   }
3993   if (ConstantCount > 1) {
3994     FLOAT* f = (FLOAT*)pConstantData;
3995     UINT i;
3996     TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3997     for (i = 0; i < ConstantCount; ++i) {
3998       TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3999       f += 4;
4000     }
4001   } else { 
4002     FLOAT* f = (FLOAT*) pConstantData;
4003     TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4004   }
4005   This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4006   memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4007   return D3D_OK;
4008 }
4009 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4010   ICOM_THIS(IDirect3DDevice8Impl,iface);
4011
4012   TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4013   if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4014     return D3DERR_INVALIDCALL;
4015   }
4016   if (NULL == pConstantData) {
4017     return D3DERR_INVALIDCALL;
4018   }
4019   memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4020   return D3D_OK;
4021 }
4022 HRESULT  WINAPI  IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4023     IDirect3DPixelShaderImpl* object;
4024
4025     object = PIXEL_SHADER(Handle);
4026     if (NULL == object) {
4027       return D3DERR_INVALIDCALL;
4028     } 
4029     return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4030 }
4031 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4032     ICOM_THIS(IDirect3DDevice8Impl,iface);
4033     FIXME("(%p) : stub\n", This);    return D3D_OK;
4034 }
4035 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4036     ICOM_THIS(IDirect3DDevice8Impl,iface);
4037     FIXME("(%p) : stub\n", This);    return D3D_OK;
4038 }
4039 HRESULT  WINAPI  IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4040     ICOM_THIS(IDirect3DDevice8Impl,iface);
4041     FIXME("(%p) : stub\n", This);    return D3D_OK;
4042 }
4043
4044 HRESULT  WINAPI  IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4045     IDirect3DVertexBuffer8 *oldSrc;
4046     ICOM_THIS(IDirect3DDevice8Impl,iface);
4047
4048     oldSrc = This->StateBlock->stream_source[StreamNumber];
4049     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4050
4051     This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4052     This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4053     This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4054     This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4055
4056     /* Handle recording of state blocks */
4057     if (This->isRecordingState) {
4058         TRACE("Recording... not performing anything\n");
4059         return D3D_OK;
4060     }
4061
4062     if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4063     if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4064     return D3D_OK;
4065 }
4066 HRESULT  WINAPI  IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4067     ICOM_THIS(IDirect3DDevice8Impl,iface);
4068     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4069     *pStream = This->StateBlock->stream_source[StreamNumber];
4070     *pStride = This->StateBlock->stream_stride[StreamNumber];
4071     IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4072     return D3D_OK;
4073 }
4074
4075
4076 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4077 {
4078     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4079     IDirect3DDevice8Impl_QueryInterface,
4080     IDirect3DDevice8Impl_AddRef,
4081     IDirect3DDevice8Impl_Release,
4082     IDirect3DDevice8Impl_TestCooperativeLevel,
4083     IDirect3DDevice8Impl_GetAvailableTextureMem,
4084     IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4085     IDirect3DDevice8Impl_GetDirect3D,
4086     IDirect3DDevice8Impl_GetDeviceCaps,
4087     IDirect3DDevice8Impl_GetDisplayMode,
4088     IDirect3DDevice8Impl_GetCreationParameters,
4089     IDirect3DDevice8Impl_SetCursorProperties,
4090     IDirect3DDevice8Impl_SetCursorPosition,
4091     IDirect3DDevice8Impl_ShowCursor,
4092     IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4093     IDirect3DDevice8Impl_Reset,
4094     IDirect3DDevice8Impl_Present,
4095     IDirect3DDevice8Impl_GetBackBuffer,
4096     IDirect3DDevice8Impl_GetRasterStatus,
4097     IDirect3DDevice8Impl_SetGammaRamp,
4098     IDirect3DDevice8Impl_GetGammaRamp,
4099     IDirect3DDevice8Impl_CreateTexture,
4100     IDirect3DDevice8Impl_CreateVolumeTexture,
4101     IDirect3DDevice8Impl_CreateCubeTexture,
4102     IDirect3DDevice8Impl_CreateVertexBuffer,
4103     IDirect3DDevice8Impl_CreateIndexBuffer,
4104     IDirect3DDevice8Impl_CreateRenderTarget,
4105     IDirect3DDevice8Impl_CreateDepthStencilSurface,
4106     IDirect3DDevice8Impl_CreateImageSurface,
4107     IDirect3DDevice8Impl_CopyRects,
4108     IDirect3DDevice8Impl_UpdateTexture,
4109     IDirect3DDevice8Impl_GetFrontBuffer,
4110     IDirect3DDevice8Impl_SetRenderTarget,
4111     IDirect3DDevice8Impl_GetRenderTarget,
4112     IDirect3DDevice8Impl_GetDepthStencilSurface,
4113     IDirect3DDevice8Impl_BeginScene,
4114     IDirect3DDevice8Impl_EndScene,
4115     IDirect3DDevice8Impl_Clear,
4116     IDirect3DDevice8Impl_SetTransform,
4117     IDirect3DDevice8Impl_GetTransform,
4118     IDirect3DDevice8Impl_MultiplyTransform,
4119     IDirect3DDevice8Impl_SetViewport,
4120     IDirect3DDevice8Impl_GetViewport,
4121     IDirect3DDevice8Impl_SetMaterial,
4122     IDirect3DDevice8Impl_GetMaterial,
4123     IDirect3DDevice8Impl_SetLight,
4124     IDirect3DDevice8Impl_GetLight,
4125     IDirect3DDevice8Impl_LightEnable,
4126     IDirect3DDevice8Impl_GetLightEnable,
4127     IDirect3DDevice8Impl_SetClipPlane,
4128     IDirect3DDevice8Impl_GetClipPlane,
4129     IDirect3DDevice8Impl_SetRenderState,
4130     IDirect3DDevice8Impl_GetRenderState,
4131     IDirect3DDevice8Impl_BeginStateBlock,
4132     IDirect3DDevice8Impl_EndStateBlock,
4133     IDirect3DDevice8Impl_ApplyStateBlock,
4134     IDirect3DDevice8Impl_CaptureStateBlock,
4135     IDirect3DDevice8Impl_DeleteStateBlock,
4136     IDirect3DDevice8Impl_CreateStateBlock,
4137     IDirect3DDevice8Impl_SetClipStatus,
4138     IDirect3DDevice8Impl_GetClipStatus,
4139     IDirect3DDevice8Impl_GetTexture,
4140     IDirect3DDevice8Impl_SetTexture,
4141     IDirect3DDevice8Impl_GetTextureStageState,
4142     IDirect3DDevice8Impl_SetTextureStageState,
4143     IDirect3DDevice8Impl_ValidateDevice,
4144     IDirect3DDevice8Impl_GetInfo,
4145     IDirect3DDevice8Impl_SetPaletteEntries,
4146     IDirect3DDevice8Impl_GetPaletteEntries,
4147     IDirect3DDevice8Impl_SetCurrentTexturePalette,
4148     IDirect3DDevice8Impl_GetCurrentTexturePalette,
4149     IDirect3DDevice8Impl_DrawPrimitive,
4150     IDirect3DDevice8Impl_DrawIndexedPrimitive,
4151     IDirect3DDevice8Impl_DrawPrimitiveUP,
4152     IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4153     IDirect3DDevice8Impl_ProcessVertices,
4154     IDirect3DDevice8Impl_CreateVertexShader,
4155     IDirect3DDevice8Impl_SetVertexShader,
4156     IDirect3DDevice8Impl_GetVertexShader,
4157     IDirect3DDevice8Impl_DeleteVertexShader,
4158     IDirect3DDevice8Impl_SetVertexShaderConstant,
4159     IDirect3DDevice8Impl_GetVertexShaderConstant,
4160     IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4161     IDirect3DDevice8Impl_GetVertexShaderFunction,
4162     IDirect3DDevice8Impl_SetStreamSource,
4163     IDirect3DDevice8Impl_GetStreamSource,
4164     IDirect3DDevice8Impl_SetIndices,
4165     IDirect3DDevice8Impl_GetIndices,
4166     IDirect3DDevice8Impl_CreatePixelShader,
4167     IDirect3DDevice8Impl_SetPixelShader,
4168     IDirect3DDevice8Impl_GetPixelShader,
4169     IDirect3DDevice8Impl_DeletePixelShader,
4170     IDirect3DDevice8Impl_SetPixelShaderConstant,
4171     IDirect3DDevice8Impl_GetPixelShaderConstant,
4172     IDirect3DDevice8Impl_GetPixelShaderFunction,
4173     IDirect3DDevice8Impl_DrawRectPatch,
4174     IDirect3DDevice8Impl_DrawTriPatch,
4175     IDirect3DDevice8Impl_DeletePatch
4176 };
4177
4178 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4179 {
4180 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4181   ICOM_THIS(IDirect3DDevice8Impl,iface);
4182
4183   ENTER_GL();
4184
4185 #if 0
4186   if (This->glCtx != This->render_ctx) {
4187     glXDestroyContext(This->display, This->render_ctx);
4188     This->render_ctx = This->glCtx;
4189   }
4190 #endif
4191   if (This->win != This->drawable) {
4192     glXDestroyPbuffer(This->display, This->drawable);
4193     This->drawable = This->win;
4194   }
4195
4196   LEAVE_GL();
4197
4198 #endif
4199   return D3D_OK;
4200 }
4201
4202 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4203                                                 IDirect3DSurface8* RenderSurface, 
4204                                                 IDirect3DSurface8* StencilSurface) {
4205
4206   HRESULT ret =  D3DERR_INVALIDCALL; 
4207   /**
4208    * Currently only active for GLX >= 1.3
4209    * for others versions we'll have to use GLXPixmaps
4210    *
4211    * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4212    * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4213    * so only check OpenGL version
4214    */
4215 #if defined(GL_VERSION_1_3) 
4216   GLXFBConfig* cfgs = NULL;
4217   int nCfgs = 0;
4218   int attribs[256];
4219   int nAttribs = 0;
4220   D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4221   D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4222   UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4223   UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4224   IDirect3DSurface8Impl* tmp;
4225
4226   ICOM_THIS(IDirect3DDevice8Impl,iface);
4227  
4228 #define PUSH1(att)        attribs[nAttribs++] = (att); 
4229 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4230
4231   PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4232   PUSH2(GLX_X_RENDERABLE,  TRUE);
4233   PUSH2(GLX_DOUBLEBUFFER, TRUE);
4234   
4235   switch (BackBufferFormat) {
4236     /* color buffer */
4237   case D3DFMT_P8:
4238     PUSH2(GLX_RENDER_TYPE,  GLX_COLOR_INDEX_BIT);
4239     PUSH2(GLX_BUFFER_SIZE,  8);
4240     PUSH2(GLX_DOUBLEBUFFER, TRUE);
4241     break;
4242     
4243   case D3DFMT_R3G3B2:
4244     PUSH2(GLX_RENDER_TYPE,  GLX_RGBA_BIT);
4245     PUSH2(GLX_RED_SIZE,     3);
4246     PUSH2(GLX_GREEN_SIZE,   3);
4247     PUSH2(GLX_BLUE_SIZE,    2);
4248     break;
4249     
4250   case D3DFMT_A1R5G5B5:
4251     PUSH2(GLX_ALPHA_SIZE,   1);
4252   case D3DFMT_X1R5G5B5:
4253     PUSH2(GLX_RED_SIZE,     5);
4254     PUSH2(GLX_GREEN_SIZE,   5);
4255     PUSH2(GLX_BLUE_SIZE,    5);
4256     break;
4257     
4258   case D3DFMT_R5G6B5:
4259     PUSH2(GLX_RED_SIZE,     5);
4260     PUSH2(GLX_GREEN_SIZE,   6);
4261     PUSH2(GLX_BLUE_SIZE,    5);
4262     break;
4263     
4264   case D3DFMT_A4R4G4B4:
4265     PUSH2(GLX_ALPHA_SIZE,   4);
4266   case D3DFMT_X4R4G4B4:
4267     PUSH2(GLX_RED_SIZE,     4);
4268     PUSH2(GLX_GREEN_SIZE,   4);
4269     PUSH2(GLX_BLUE_SIZE,    4);
4270     break;
4271     
4272   case D3DFMT_A8R8G8B8:
4273     PUSH2(GLX_ALPHA_SIZE,   8);
4274   case D3DFMT_R8G8B8:
4275   case D3DFMT_X8R8G8B8:
4276     PUSH2(GLX_RED_SIZE,     8);
4277     PUSH2(GLX_GREEN_SIZE,   8);
4278     PUSH2(GLX_BLUE_SIZE,    8);
4279     break;
4280
4281   default:
4282     break;
4283   }
4284    
4285   switch (StencilBufferFormat) { 
4286   case D3DFMT_D16_LOCKABLE:
4287   case D3DFMT_D16:
4288     PUSH2(GLX_DEPTH_SIZE,   16);
4289     break;
4290     
4291   case D3DFMT_D15S1:
4292     PUSH2(GLX_DEPTH_SIZE,   15);
4293     break;
4294     
4295   case D3DFMT_D24X8:
4296     PUSH2(GLX_DEPTH_SIZE,   24);
4297     break;
4298     
4299   case D3DFMT_D24X4S4:
4300     PUSH2(GLX_DEPTH_SIZE,   24);
4301     PUSH2(GLX_STENCIL_SIZE, 4);
4302     break;
4303     
4304   case D3DFMT_D24S8:
4305     PUSH2(GLX_DEPTH_SIZE,   24);
4306     PUSH2(GLX_STENCIL_SIZE, 8);
4307     break;
4308     
4309   case D3DFMT_D32:
4310     PUSH2(GLX_DEPTH_SIZE,   32);
4311     break;
4312
4313   default:
4314     break;
4315   }
4316
4317   PUSH1(None);
4318   
4319   ENTER_GL();
4320
4321   cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4322   if (NULL != cfgs) {
4323 #if 0
4324     int i;
4325     for (i = 0; i < nCfgs; ++i) {
4326       TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4327     }
4328 #endif
4329
4330     if (NULL != This->renderTarget) {
4331       GLenum prev_read;      
4332       glFlush();
4333       vcheckGLcall("glFlush");
4334
4335 #if 0
4336       /** very very usefull debug code */
4337       glXSwapBuffers(This->display, This->drawable);   
4338       printf("Hit Enter to get next frame ...\n");
4339       getchar();
4340 #endif
4341
4342       glGetIntegerv(GL_READ_BUFFER, &prev_read);
4343       vcheckGLcall("glIntegerv");
4344       glReadBuffer(GL_BACK);
4345       vcheckGLcall("glReadBuffer");
4346       {
4347         long j;
4348         long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4349
4350         if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4351             pitch = pitch / 2;
4352
4353         for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4354           glReadPixels(0, 
4355                        This->renderTarget->myDesc.Height - j - 1, 
4356                        This->renderTarget->myDesc.Width, 
4357                        1,
4358                        D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format), 
4359                        D3DFmt2GLType(This, This->renderTarget->myDesc.Format), 
4360                        This->renderTarget->allocatedMemory + j * pitch);
4361           vcheckGLcall("glReadPixels");
4362         }
4363       }      
4364       glReadBuffer(prev_read);
4365       vcheckGLcall("glReadBuffer");
4366     }
4367
4368     if (BackBufferFormat != This->renderTarget->myDesc.Format && 
4369         StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4370       nAttribs = 0;
4371       PUSH2(GLX_PBUFFER_WIDTH,  Width);
4372       PUSH2(GLX_PBUFFER_HEIGHT, Height);
4373       PUSH1(None);
4374       This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4375             
4376       This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4377       if (NULL == This->render_ctx) {
4378         ERR("cannot create glxContext\n"); 
4379       }
4380
4381       glFlush();
4382       glXSwapBuffers(This->display, This->drawable);
4383       if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4384         TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4385       }
4386       checkGLcall("glXMakeContextCurrent");
4387     }
4388
4389     tmp = This->renderTarget;
4390     This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4391     IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4392     IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4393
4394     tmp = This->stencilBufferTarget;
4395     This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4396     if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4397     if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4398
4399     ret = D3D_OK;
4400
4401   } else {
4402     ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4403   }
4404
4405 #undef PUSH1
4406 #undef PUSH2
4407
4408   LEAVE_GL();
4409
4410 #endif
4411
4412   return ret;
4413 }