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