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