Fixes for -Wmissing-declaration and -Wwrite-string warnings.
[wine] / dlls / wined3d / device.c
1 /*
2  * IWineD3DDevice implementation
3  *
4  * Copyright 2002-2005 Jason Edmeades
5  * Copyright 2003-2004 Raphael Junqueira
6  * Copyright 2004 Christian Costa
7  * Copyright 2005 Oliver Stieber
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include "config.h"
25 #include "wined3d_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
32
33 /* helper macros */
34 #define D3DMEMCHECK(object, ppResult) if(NULL == object){ *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
35
36 #define D3DCREATEOBJECTINSTANCE(object, type){ \
37     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
38     D3DMEMCHECK(object, pp##type); \
39     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
40     object->wineD3DDevice = This; \
41     object->parent       = parent; \
42     object->ref          = 1; \
43     *pp##type = (IWineD3D##type *) object; \
44 }
45
46 #define  D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype){ \
47     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
48     D3DMEMCHECK(object, pp##type); \
49     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
50     object->resource.wineD3DDevice   = This; \
51     object->resource.parent          = parent; \
52     object->resource.resourceType    = d3dtype; \
53     object->resource.ref             = 1; \
54     object->resource.pool            = Pool; \
55     object->resource.format          = Format; \
56     object->resource.usage           = Usage; \
57     object->resource.size            = 0; \
58     object->resource.allocatedMemory = 0; \
59     *pp##type = (IWineD3D##type *) object; \
60 }
61
62 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
63     _basetexture.levels     = Levels; \
64     _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
65     _basetexture.LOD        = 0; \
66 }
67
68 /**********************************************************
69  * Global variable / Constants follow
70  **********************************************************/
71 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
72
73 /**********************************************************
74  * Utility functions follow
75  **********************************************************/
76 /* Convert the D3DLIGHT properties into equivalent gl lights */
77 void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
78
79     float quad_att;
80     float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
81     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
82
83     /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
84     glMatrixMode(GL_MODELVIEW);
85     glPushMatrix();
86     glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
87
88     /* Diffuse: */
89     colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
90     colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
91     colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
92     colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
93     glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
94     checkGLcall("glLightfv");
95
96     /* Specular */
97     colRGBA[0] = lightInfo->OriginalParms.Specular.r;
98     colRGBA[1] = lightInfo->OriginalParms.Specular.g;
99     colRGBA[2] = lightInfo->OriginalParms.Specular.b;
100     colRGBA[3] = lightInfo->OriginalParms.Specular.a;
101     glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
102     checkGLcall("glLightfv");
103
104     /* Ambient */
105     colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
106     colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
107     colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
108     colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
109     glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
110     checkGLcall("glLightfv");
111
112     /* Attenuation - Are these right? guessing... */
113     glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
114     checkGLcall("glLightf");
115     glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
116     checkGLcall("glLightf");
117
118     quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
119     if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
120     glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
121     checkGLcall("glLightf");
122
123     switch (lightInfo->OriginalParms.Type) {
124     case D3DLIGHT_POINT:
125         /* Position */
126         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
127         checkGLcall("glLightfv");
128         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
129         checkGLcall("glLightf");
130         /* FIXME: Range */
131         break;
132
133     case D3DLIGHT_SPOT:
134         /* Position */
135         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
136         checkGLcall("glLightfv");
137         /* Direction */
138         glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
139         checkGLcall("glLightfv");
140         glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
141         checkGLcall("glLightf");
142         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
143         checkGLcall("glLightf");
144         /* FIXME: Range */
145         break;
146
147     case D3DLIGHT_DIRECTIONAL:
148         /* Direction */
149         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
150         checkGLcall("glLightfv");
151         glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
152         checkGLcall("glLightf");
153         glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
154         checkGLcall("glLightf");
155         break;
156
157     default:
158         FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
159     }
160
161     /* Restore the modelview matrix */
162     glPopMatrix();
163 }
164
165 /* Apply the current values to the specified texture stage */
166 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
167     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
168     int i = 0;
169     float col[4];
170     BOOL changeTexture = TRUE;
171
172     TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
173     for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
174
175         BOOL skip = FALSE;
176
177         switch (i) {
178         /* Performance: For texture states where multiples effect the outcome, only bother
179               applying the last one as it will pick up all the other values                */
180         case D3DTSS_COLORARG0:  /* Will be picked up when setting color op */
181         case D3DTSS_COLORARG1:  /* Will be picked up when setting color op */
182         case D3DTSS_COLORARG2:  /* Will be picked up when setting color op */
183         case D3DTSS_ALPHAARG0:  /* Will be picked up when setting alpha op */
184         case D3DTSS_ALPHAARG1:  /* Will be picked up when setting alpha op */
185         case D3DTSS_ALPHAARG2:  /* Will be picked up when setting alpha op */
186            skip = TRUE;
187            break;
188
189         /* Performance: If the texture states only impact settings for the texture unit 
190              (compared to the texture object) then there is no need to reapply them. The
191              only time they need applying is the first time, since we cheat and put the  
192              values into the stateblock without applying.                                
193              Per-texture unit: texture function (eg. combine), ops and args
194                                texture env color                                               
195                                texture generation settings                               
196            Note: Due to some special conditions there may be a need to do particular ones
197              of these, which is what the Flags allows                                     */
198         case D3DTSS_COLOROP:       
199         case D3DTSS_TEXCOORDINDEX:
200             if (!(Flags == REAPPLY_ALL)) skip=TRUE;
201             break;
202
203         case D3DTSS_ALPHAOP:       
204             if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
205             break;
206
207         default:
208             skip = FALSE;
209         }
210
211         if (skip == FALSE) {
212            /* Performance: Only change to this texture if we have to */
213            if (changeTexture) {
214                /* Make appropriate texture active */
215                if (GL_SUPPORT(ARB_MULTITEXTURE)) {
216                    GLACTIVETEXTURE(Stage);
217                 } else if (Stage > 0) {
218                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
219                 }
220                 changeTexture = FALSE;
221            }
222
223            /* Now apply the change */
224            IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
225         }
226     }
227
228     /* Note the D3DRS value applies to all textures, but GL has one
229      *  per texture, so apply it now ready to be used!
230      */
231     D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
232     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
233     checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
234
235     TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);   
236 }
237
238 /**********************************************************
239  * IUnknown parts follows
240  **********************************************************/
241
242 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
243 {
244     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
245     /* FIXME: This needs to extend an IWineD3DBaseObject */
246     
247     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
248     if (IsEqualGUID(riid, &IID_IUnknown)        
249         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
250         IUnknown_AddRef(iface);
251         *ppobj = This;
252         return D3D_OK;
253     }
254     
255     return E_NOINTERFACE;
256 }
257
258 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
259     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
260     ULONG refCount = InterlockedIncrement(&This->ref);
261
262     TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
263     return refCount;
264 }
265
266 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
267     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
268     ULONG refCount = InterlockedDecrement(&This->ref);
269
270     TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
271
272     if (!refCount) {
273         /* TODO: Clean up all the surfaces and textures! */
274         /* FIXME: Create targets and state blocks in d3d8 */        
275         if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
276             /* NOTE: You must release the parent if the objects was created via a callback
277             ** ***************************/
278             IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
279         }
280         IWineD3D_Release(This->wineD3D);
281         HeapFree(GetProcessHeap(), 0, This);
282     }
283     return refCount;
284 }
285
286 /**********************************************************
287  * IWineD3DDevice implementation follows
288  **********************************************************/
289 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
290     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
291     *pParent = This->parent;
292     IUnknown_AddRef(This->parent);
293     return D3D_OK;
294 }
295
296 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, 
297                              DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
298                              IUnknown *parent) {
299     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
300     IWineD3DVertexBufferImpl *object;
301     WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
302     D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER)
303     
304     object->resource.size             = Size;
305     object->resource.allocatedMemory  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
306     object->FVF                       = FVF;
307
308     TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
309     *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
310
311     return D3D_OK;
312 }
313
314 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage, 
315                                                     WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
316                                                     HANDLE *sharedHandle, IUnknown *parent) {
317     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
318     IWineD3DIndexBufferImpl *object;
319     TRACE("(%p) Creating index buffer\n", This);
320     
321     /* Allocate the storage for the device */
322     D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER)
323     
324     object->resource.size                   = Length;
325     object->resource.allocatedMemory        = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
326
327     TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format, 
328                            debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
329     *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
330
331     return D3D_OK;
332 }
333
334 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
335   
336     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
337     IWineD3DStateBlockImpl *object;
338
339     D3DCREATEOBJECTINSTANCE(object, StateBlock)
340     object->blockType     = Type; 
341
342     /* Special case - Used during initialization to produce a placeholder stateblock
343           so other functions called can update a state block                         */
344     if (Type == (D3DSTATEBLOCKTYPE) 0) {
345         /* Don't bother increasing the reference count otherwise a device will never
346            be freed due to circular dependencies                                   */
347         return D3D_OK;
348     }
349
350     /* Otherwise, might as well set the whole state block to the appropriate values */
351     IWineD3DDevice_AddRef(iface);
352     memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
353     FIXME("unfinished - needs to set up changed and set attributes\n");
354     return D3D_OK;
355 }
356
357
358 /* ************************************
359 MSDN:
360 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
361
362 Discard
363  [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. 
364
365 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
366
367 ******************************** */
368  
369 HRESULT  WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
370     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;    
371     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
372     unsigned int pow2Width, pow2Height;
373
374     TRACE("(%p) Create surface\n",This);
375     
376     /** FIXME: Check ranges on the inputs are valid 
377      * MSDN
378      *   MultisampleQuality
379      *    [in] Quality level. The valid range is between zero and one less than the level
380      *    returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. 
381      *    Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
382      *    values of paired render targets, depth stencil surfaces, and the MultiSample type
383      *    must all match.
384       *******************************/
385
386
387     /**
388     * TODO: Discard MSDN
389     * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. 
390     *
391     * If this flag is set, the contents of the depth stencil buffer will be
392     * invalid after calling either IDirect3DDevice9::Present or  * IDirect3DDevice9::SetDepthStencilSurface
393     * with a different depth surface.
394     *
395     *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
396     ***************************/
397   
398     if(MultisampleQuality < 0) { 
399         FIXME("Invalid multisample level %ld \n", MultisampleQuality);  
400         return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
401     }
402     
403     if(MultisampleQuality > 0){
404         FIXME("MultisampleQuality set to %ld, bstituting 0  \n" , MultisampleQuality);  
405         MultisampleQuality=0;
406     }
407
408     /* Non-power2 support */
409
410     /* Find the nearest pow2 match */
411     pow2Width = pow2Height = 1;
412     while (pow2Width < Width) pow2Width <<= 1;
413     while (pow2Height < Height) pow2Height <<= 1;
414
415     if(pow2Width > Width || pow2Height > Height){
416         FIXME("non-power-two textures unsupported\n"); /* OpenGL provides support for these gratis */
417         return D3DERR_NOTAVAILABLE;
418     }
419
420         
421     /** TODO: Check against the maximum texture sizes supported by the video card **/
422     
423     D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE)
424     object->container = (IUnknown*) This;
425             
426     object->currentDesc.Width      = Width;
427     object->currentDesc.Height     = Height;
428     object->currentDesc.Level      = Level;
429     object->currentDesc.MultiSampleType    = MultiSample;
430     object->currentDesc.MultiSampleQuality = MultisampleQuality;
431     object->discard    = Discard;
432     object->bytesPerPixel = D3DFmtGetBpp(This, Format);
433     
434     /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
435      *  it is based around 4x4 pixel blocks it requires padding, so allocate enough
436      *  space!
437       *********************************/
438     if (Format == WINED3DFMT_DXT1) {
439         /* DXT1 is half byte per pixel */
440         object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2;
441         
442     } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
443                Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
444         object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
445     } else {
446         object->resource.size = (Width * object->bytesPerPixel) * Height;
447     }
448     
449     TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
450
451 #if 0
452     /* TODO: Check that we have enough video ram left */
453     if(Pool == D3DPOOL_DEFAULT  && IWineD3DDevice_GetAvailableTextureMem(iface) <= object->currentDesc.Size){
454         TRACE("Out of 'bogus' video memory\n");
455         HeapFree(GetProcessHeap(),0,object);
456         *ppSurface = NULL;
457         return D3DERR_OUTOFVIDEOMEMORY;
458     }
459 #endif
460     
461     /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
462     * this function is too deap to need to care about things like this.
463     * Levels need to be checked too, and possibly Type wince they all affect what can be done.
464     * ****************************************/
465     switch(Pool) {
466     case D3DPOOL_SCRATCH:
467         if(Lockable == FALSE)
468             FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
469                 which are mutually exclusive, setting lockable to true\n");
470                 Lockable = TRUE;
471     break;
472     case D3DPOOL_SYSTEMMEM:
473         if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
474                                     this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
475     case D3DPOOL_MANAGED:
476         if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
477                                              Usage of DYNAMIC which are mutually exclusive, not doing \
478                                              anything just telling you.\n");
479     break;    
480     case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
481         if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
482            && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
483             FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
484     break;
485     default:     
486         FIXME("(%p) Unknown pool %d\n", This, Pool);
487     break;
488     };
489     
490     if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT){
491         FIXME("Trying to create a render target that isn't in the default pool\n");
492     }
493
494
495     object->locked   = FALSE;
496     object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
497     /* TODO: memory management */
498     object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
499     if(object->resource.allocatedMemory == NULL ) {
500         FIXME("Out of memory!\n");
501         HeapFree(GetProcessHeap(),0,object);
502         *ppSurface = NULL;
503         return D3DERR_OUTOFVIDEOMEMORY;
504     }
505     
506
507     IWineD3DSurface_CleanDirtyRect(*ppSurface);
508     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
509            This, Width, Height, Format, debug_d3dformat(Format),
510            (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
511     return D3D_OK;
512
513 }
514
515 HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
516                                                  DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
517                                                  IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
518                                                  D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
519
520     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
521     IWineD3DTextureImpl *object;    
522     unsigned int i;
523     UINT tmpW;
524     UINT tmpH;
525     HRESULT hr;
526
527     TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
528
529     D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE);
530     D3DINITILIZEBASETEXTURE(object->baseTexture);    
531     object->width  = Width;
532     object->height = Height;
533     
534     /* Calculate levels for mip mapping */
535     if (Levels == 0) {
536         TRACE("calculating levels %d\n", object->baseTexture.levels);
537         object->baseTexture.levels++;
538         tmpW = Width;
539         tmpH = Height;
540         while (tmpW > 1 && tmpH > 1) {
541             tmpW = max(1, tmpW >> 1);
542             tmpH = max(1, tmpH >> 1);
543             object->baseTexture.levels++;
544         }
545         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
546     }
547     
548     /* Generate all the surfaces */
549     tmpW = Width;
550     tmpH = Height;
551     for (i = 0; i < object->baseTexture.levels; i++) 
552     {
553         /* use the callback to create the texture surface */
554         hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
555         if(hr!= D3D_OK){
556             int j;
557             FIXME("Failed to create surface  %p \n",object);
558             /* clean up */
559             for(j=0;j<i;j++){
560                 IWineD3DSurface_Release(object->surfaces[j]);
561             }
562             /* heap free object */
563             HeapFree(GetProcessHeap(),0,object);
564
565             *ppTexture = NULL;
566             return hr;
567         }
568         
569         IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
570         TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
571         /* calculate the next mipmap level */
572         tmpW = max(1, tmpW >> 1);
573         tmpH = max(1, tmpH >> 1);
574     }
575     
576     TRACE("(%p) : Created  texture %p\n", This, object);
577     return D3D_OK;
578 }
579
580 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface, 
581                                                       UINT Width, UINT Height, UINT Depth, 
582                                                       UINT Levels, DWORD Usage, 
583                                                       WINED3DFORMAT Format, D3DPOOL Pool, 
584                                                       IWineD3DVolumeTexture** ppVolumeTexture,
585                                                       HANDLE* pSharedHandle, IUnknown *parent,
586                                                       D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
587
588     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
589     IWineD3DVolumeTextureImpl *object;
590     unsigned int               i;
591     UINT                       tmpW;
592     UINT                       tmpH;
593     UINT                       tmpD;
594
595     D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE);
596     D3DINITILIZEBASETEXTURE(object->baseTexture);
597     
598     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
599           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
600
601     object->width  = Width;
602     object->height = Height;
603     object->depth  = Depth;
604
605     /* Calculate levels for mip mapping */
606     if (Levels == 0) {
607         object->baseTexture.levels++;
608         tmpW = Width;
609         tmpH = Height;
610         tmpD = Depth;
611         while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
612             tmpW = max(1, tmpW >> 1);
613             tmpH = max(1, tmpH >> 1);
614             tmpD = max(1, tmpD >> 1);
615             object->baseTexture.levels++;
616         }
617         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
618     }
619
620     /* Generate all the surfaces */
621     tmpW = Width;
622     tmpH = Height;
623     tmpD = Depth;
624
625     for (i = 0; i < object->baseTexture.levels; i++) 
626     {
627         /* Create the volume */
628         D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage, 
629                            (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
630         IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
631
632         tmpW = max(1, tmpW >> 1);
633         tmpH = max(1, tmpH >> 1);
634         tmpD = max(1, tmpD >> 1);
635     }
636
637     *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
638     TRACE("(%p) : Created volume texture %p\n", This, object);
639     return D3D_OK;
640 }
641
642 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface, 
643                                                UINT Width, UINT Height, UINT Depth, 
644                                                DWORD Usage, 
645                                                WINED3DFORMAT Format, D3DPOOL Pool, 
646                                                IWineD3DVolume** ppVolume,
647                                                HANDLE* pSharedHandle, IUnknown *parent) {
648
649     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
650     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
651
652     D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME)
653
654     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
655           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
656
657     object->currentDesc.Width   = Width;
658     object->currentDesc.Height  = Height;
659     object->currentDesc.Depth   = Depth;
660     object->bytesPerPixel       = D3DFmtGetBpp(This, Format);
661
662     /** Note: Volume textures cannot be dxtn, hence no need to check here **/
663     object->resource.size       = (Width * object->bytesPerPixel) * Height * Depth; 
664     object->resource.allocatedMemory     = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
665     object->lockable            = TRUE;
666     object->locked              = FALSE;
667     memset(&object->lockedBox, 0, sizeof(D3DBOX));
668     object->dirty = FALSE;
669     return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
670 }
671
672 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength, 
673                                                     UINT Levels, DWORD Usage, 
674                                                     WINED3DFORMAT Format, D3DPOOL Pool, 
675                                                     IWineD3DCubeTexture** ppCubeTexture,
676                                                     HANDLE* pSharedHandle, IUnknown *parent,
677                                                     D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
678
679    IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
680    IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
681    unsigned int             i,j;
682    UINT                     tmpW;
683    HRESULT                  hr;
684
685    D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE);
686    D3DINITILIZEBASETEXTURE(object->baseTexture);
687
688    TRACE("(%p) Create Cube Texture \n", This);
689    
690    object->edgeLength           = EdgeLength;
691
692    /* Calculate levels for mip mapping */
693    if (Levels == 0) {
694        object->baseTexture.levels++;
695        tmpW = EdgeLength;
696        while (tmpW > 1) {
697            tmpW = max(1, tmpW / 2);
698            object->baseTexture.levels++;
699        }
700        TRACE("Calculated levels = %d\n", object->baseTexture.levels);
701    }
702
703     /* Generate all the surfaces */
704     tmpW = EdgeLength;
705     for (i = 0; i < object->baseTexture.levels; i++) {
706
707         /* Create the 6 faces */
708         for (j = 0; j < 6; j++) {
709                             
710             hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
711                                    i /* Level */, &object->surfaces[j][i],pSharedHandle);
712         
713             if(hr!= D3D_OK){
714                 /* clean up */
715                 int k;
716                 int l;
717                 for (l=0;l<j;l++) {
718                     IWineD3DSurface_Release(object->surfaces[j][i]);
719                 }
720                 for (k=0;k<i;k++) {
721                     for (l=0;l<6;l++) {
722                     IWineD3DSurface_Release(object->surfaces[l][j]);
723                     }
724                 }
725
726                 FIXME("(%p) Failed to create surface\n",object);
727                 HeapFree(GetProcessHeap(),0,object);
728                 *ppCubeTexture = NULL;
729                 return hr;
730             }
731             IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
732             TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
733         }
734         tmpW = max(1, tmpW >> 1);
735     }
736
737     TRACE("(%p) : Created Cube Texture %p\n", This, object);
738     *ppCubeTexture = (IWineD3DCubeTexture *) object;
739     return D3D_OK;
740 }
741
742 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent){
743     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
744     IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
745
746     if(NULL == ppQuery){
747         /* Just a check to see if we support this type of query */
748         HRESULT hr = D3DERR_NOTAVAILABLE;
749         /* Lie and say everything is good (we can return ok fake data from a stub) */
750         switch(Type){
751         case WINED3DQUERYTYPE_VCACHE:
752         case WINED3DQUERYTYPE_RESOURCEMANAGER:
753         case WINED3DQUERYTYPE_VERTEXSTATS:
754         case WINED3DQUERYTYPE_EVENT:
755         case WINED3DQUERYTYPE_OCCLUSION:
756         case WINED3DQUERYTYPE_TIMESTAMP:
757         case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
758         case WINED3DQUERYTYPE_TIMESTAMPFREQ:
759         case WINED3DQUERYTYPE_PIPELINETIMINGS:
760         case WINED3DQUERYTYPE_INTERFACETIMINGS:
761         case WINED3DQUERYTYPE_VERTEXTIMINGS:
762         case WINED3DQUERYTYPE_PIXELTIMINGS:
763         case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
764         case WINED3DQUERYTYPE_CACHEUTILIZATION:
765             hr = D3D_OK;
766         break;
767         default:
768             FIXME("(%p) Unhandled query type %d\n",This , Type);       
769         }
770         FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
771         return hr;
772     }
773
774     D3DCREATEOBJECTINSTANCE(object, Query)
775     object->type         = Type;
776     object->extendedData = 0;
777     TRACE("(%p) : Created Query %p\n", This, object);
778     return D3D_OK;
779 }
780
781 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
782 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS*  pPresentationParameters,                                                                   void** ppSwapChain,
783                                                             IUnknown* parent,
784                                                             D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
785                                                             D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){
786     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
787     *ppSwapChain = NULL;
788     FIXME("(%p) : Stub\n",This);
789     return D3D_OK;
790 }
791
792 /** NOTE: These are ahead of the other getters and setters to save using a forward declartion **/
793 UINT     WINAPI  IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
794     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
795     
796     FIXME("(%p) : Stub\n",This);
797     return 1;
798 }
799
800 HRESULT  WINAPI  IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, void** pSwapChain) {
801     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
802     
803     FIXME("(%p) : Stub\n",This);
804     return D3D_OK;
805 }
806
807 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS*  pPresentationParameters){
808     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
809
810     FIXME("(%p) : Stub\n",This);
811     return D3D_OK;
812           
813 }
814
815 /*****
816  * Vertex Declaration
817  *****/
818  /* TODO: Get ridd of thease and put the functions in the  IWineD3DVertexDeclaration interface */
819 #if 1
820 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl * This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl * object);
821 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl * This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl * object);
822
823
824 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
825     IWineD3DDeviceImpl            *This   = (IWineD3DDeviceImpl *)iface;
826     IWineD3DVertexDeclarationImpl *object = NULL;
827     HRESULT hr = D3D_OK;
828     
829     TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);    
830     D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
831     object->allFVF = 0;
832
833     if (8 == ((IWineD3DImpl *)This->wineD3D)->dxVersion) {
834       /** @TODO */
835       hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, (const DWORD*) pDeclaration, object);
836     } else {
837       hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, (const D3DVERTEXELEMENT9*) pDeclaration, object);
838     }
839
840     return hr;
841 }
842
843
844 #else
845 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration8(IWineD3DDevice* iface, const DWORD* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
846     IWineD3DDeviceImpl            *This   = (IWineD3DDeviceImpl *)iface;
847     IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
848     HRESULT hr = D3D_OK;
849     /* TODO: replace impl usage with a call to Version*/
850     TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);    
851     D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
852     object->allFVF = 0;
853     /* TODO: get ridd of the impl usage, we should only be using interfaces */
854     hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, pDeclaration, object);
855     
856     return hr;
857 }
858
859 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration9(IWineD3DDevice* iface, const D3DVERTEXELEMENT9* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
860     IWineD3DDeviceImpl            *This   = (IWineD3DDeviceImpl *)iface;
861     IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
862     HRESULT hr = D3D_OK;
863     /* TODO: replace impl usage with a call to Version*/
864     TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);    
865     D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
866     object->allFVF = 0;
867     /* TODO: get ridd of the impl usage, we should only be using interfaces */
868     hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, pDeclaration, object);
869     
870     return hr;
871 }
872 #endif
873
874 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
875 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface,  CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent){
876     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
877     IWineD3DVertexShaderImpl *object;  /* NOTE: impl usage is ok, this is a create */
878     D3DCREATEOBJECTINSTANCE(object, VertexShader)    
879     object->function      = pFunction;
880     FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
881     return D3D_OK;
882
883 }
884
885 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent){
886     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
887     FIXME("(%p) : Stub\n", This);
888     return D3D_OK;
889 }
890
891 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D){    
892    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
893    *ppD3D= This->wineD3D;
894    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
895    IWineD3D_AddRef(*ppD3D);
896    return D3D_OK;
897     
898 }
899     
900 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
901     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
902     FIXME("Stub :(%p) returning 64Mib\n", This);
903     return 64*1024*1024;
904 }
905
906
907 /*****
908  * Get / Set FVF
909  *****/
910 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
911     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
912
913     /* Update the current state block */
914     This->updateStateBlock->fvf              = fvf;
915     This->updateStateBlock->changed.fvf      = TRUE;
916     This->updateStateBlock->set.fvf          = TRUE;
917
918     TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
919     
920     /* No difference if recording or not */
921     return D3D_OK;
922 }
923 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
924     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
925     TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
926     *pfvf = This->stateBlock->fvf;
927     return D3D_OK;
928 }
929
930 /*****
931  * Get / Set Stream Source
932  *****/
933 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
934     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
935     IWineD3DVertexBuffer     *oldSrc;
936
937     oldSrc = This->stateBlock->stream_source[StreamNumber];
938     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
939
940     This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
941     This->updateStateBlock->set.stream_source[StreamNumber]     = TRUE;
942     This->updateStateBlock->stream_stride[StreamNumber]         = Stride;
943     This->updateStateBlock->stream_source[StreamNumber]         = pStreamData;
944     This->updateStateBlock->stream_offset[StreamNumber]         = OffsetInBytes;
945
946     /* Handle recording of state blocks */
947     if (This->isRecordingState) {
948         TRACE("Recording... not performing anything\n");
949         return D3D_OK;
950     }
951
952     /* Not recording... */
953     if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
954     if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
955
956     return D3D_OK;
957 }
958
959 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
960     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
961
962     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
963     *pStream = This->stateBlock->stream_source[StreamNumber];
964     *pStride = This->stateBlock->stream_stride[StreamNumber];
965     *pOffset = This->stateBlock->stream_offset[StreamNumber];
966     if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
967     return D3D_OK;
968 }
969
970 /*Should be quite easy, just an extension of vertexdata
971 ref...
972 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
973
974 The divider is a bit odd though
975
976 VertexOffset = StartVertex / Divider * StreamStride + 
977                VertexIndex / Divider * StreamStride + StreamOffset
978
979 */
980 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider){
981     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
982     
983     FIXME("(%p) : stub\n", This);
984     return D3D_OK;
985     
986 }
987 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider){
988     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
989         
990     FIXME("(%p) : stub\n", This);
991     return D3D_OK;
992     
993 }
994
995 /*****
996  * Get / Set & Multipy Transform
997  *****/
998 HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
999     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1000
1001     /* Most of this routine, comments included copied from ddraw tree initially: */
1002     TRACE("(%p) : Transform State=%d\n", This, d3dts);
1003
1004     /* Handle recording of state blocks */
1005     if (This->isRecordingState) {
1006         TRACE("Recording... not performing anything\n");
1007         This->updateStateBlock->changed.transform[d3dts] = TRUE;
1008         This->updateStateBlock->set.transform[d3dts]     = TRUE;
1009         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1010         return D3D_OK;
1011     }
1012
1013     /*
1014      * If the new matrix is the same as the current one,
1015      * we cut off any further processing. this seems to be a reasonable
1016      * optimization because as was noticed, some apps (warcraft3 for example)
1017      * tend towards setting the same matrix repeatedly for some reason.
1018      *
1019      * From here on we assume that the new matrix is different, wherever it matters.
1020      */
1021     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1022         TRACE("The app is setting the same matrix over again\n");
1023         return D3D_OK;
1024     } else {
1025         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1026     }
1027
1028     /*
1029        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1030        where ViewMat = Camera space, WorldMat = world space.
1031
1032        In OpenGL, camera and world space is combined into GL_MODELVIEW
1033        matrix.  The Projection matrix stay projection matrix. 
1034      */
1035
1036     /* Capture the times we can just ignore the change for now */
1037     if (d3dts == D3DTS_WORLDMATRIX(0)) {
1038         This->modelview_valid = FALSE;
1039         return D3D_OK;
1040
1041     } else if (d3dts == D3DTS_PROJECTION) {
1042         This->proj_valid = FALSE;
1043         return D3D_OK;
1044
1045     } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { 
1046         /* Indexed Vertex Blending Matrices 256 -> 511  */
1047         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1048         FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1049         return D3D_OK;
1050     } 
1051     
1052     /* Now we really are going to have to change a matrix */
1053     ENTER_GL();
1054
1055     if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1056         if (d3dts < GL_LIMITS(textures)) {
1057             int tex = d3dts - D3DTS_TEXTURE0;
1058             GLACTIVETEXTURE(tex);
1059             set_texture_matrix((float *)lpmatrix, 
1060                                This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1061         }
1062
1063     } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1064         unsigned int k;
1065
1066         /* If we are changing the View matrix, reset the light and clipping planes to the new view   
1067          * NOTE: We have to reset the positions even if the light/plane is not currently
1068          *       enabled, since the call to enable it will not reset the position.                 
1069          * NOTE2: Apparently texture transforms do NOT need reapplying
1070          */
1071         
1072         PLIGHTINFOEL *lightChain = NULL;
1073         This->modelview_valid = FALSE;
1074         This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1075
1076         glMatrixMode(GL_MODELVIEW);
1077         checkGLcall("glMatrixMode(GL_MODELVIEW)");
1078         glPushMatrix();
1079         glLoadMatrixf((float *)lpmatrix);
1080         checkGLcall("glLoadMatrixf(...)");
1081
1082         /* Reset lights */
1083         lightChain = This->stateBlock->lights;
1084         while (lightChain && lightChain->glIndex != -1) {
1085             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1086             checkGLcall("glLightfv posn");
1087             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1088             checkGLcall("glLightfv dirn");
1089             lightChain = lightChain->next;
1090         }
1091
1092         /* Reset Clipping Planes if clipping is enabled */
1093         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1094             glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1095             checkGLcall("glClipPlane");
1096         }
1097         glPopMatrix();
1098
1099     } else { /* What was requested!?? */
1100         WARN("invalid matrix specified: %i\n", d3dts);
1101     }
1102
1103     /* Release lock, all done */
1104     LEAVE_GL();
1105     return D3D_OK;
1106
1107 }
1108 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1109     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1110     TRACE("(%p) : for Transform State %d\n", This, State);
1111     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1112     return D3D_OK;
1113 }
1114
1115 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1116     D3DMATRIX *mat = NULL;
1117     D3DMATRIX temp;
1118
1119     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1120      * below means it will be recorded in a state block change, but it
1121      * works regardless where it is recorded. 
1122      * If this is found to be wrong, change to StateBlock.
1123      */
1124     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1125     TRACE("(%p) : For state %u\n", This, State);
1126
1127     if (State < HIGHEST_TRANSFORMSTATE)
1128     {
1129         mat = &This->updateStateBlock->transforms[State];
1130     } else {
1131         FIXME("Unhandled transform state!!\n");
1132     }
1133
1134     /* Copied from ddraw code:  */
1135     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);
1136     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);
1137     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);
1138     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);
1139
1140     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);
1141     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);
1142     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);
1143     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);
1144
1145     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);
1146     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);
1147     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);
1148     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);
1149
1150     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);
1151     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);
1152     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);
1153     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);
1154
1155     /* Apply change via set transform - will reapply to eg. lights this way */
1156     IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1157     return D3D_OK;
1158 }
1159
1160 /*****
1161  * Get / Set Light
1162  *   WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1163  *****/
1164 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1165    you can reference any indexes you want as long as that number max are enabled at any
1166    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1167    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1168    but when recording, just build a chain pretty much of commands to be replayed.                  */
1169    
1170 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1171     float rho;
1172     PLIGHTINFOEL *object, *temp;
1173
1174     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1175     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1176
1177     /* If recording state block, just add to end of lights chain */
1178     if (This->isRecordingState) {
1179         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1180         if (NULL == object) {
1181             return D3DERR_OUTOFVIDEOMEMORY;
1182         }
1183         memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1184         object->OriginalIndex = Index;
1185         object->glIndex = -1;
1186         object->changed = TRUE;
1187
1188         /* Add to the END of the chain of lights changes to be replayed */
1189         if (This->updateStateBlock->lights == NULL) {
1190             This->updateStateBlock->lights = object;
1191         } else {
1192             temp = This->updateStateBlock->lights;
1193             while (temp->next != NULL) temp=temp->next;
1194             temp->next = object;
1195         }
1196         TRACE("Recording... not performing anything more\n");
1197         return D3D_OK;
1198     }
1199
1200     /* Ok, not recording any longer so do real work */
1201     object = This->stateBlock->lights;
1202     while (object != NULL && object->OriginalIndex != Index) object = object->next;
1203
1204     /* If we didn't find it in the list of lights, time to add it */
1205     if (object == NULL) {
1206         PLIGHTINFOEL *insertAt,*prevPos;
1207
1208         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1209         if (NULL == object) {
1210             return D3DERR_OUTOFVIDEOMEMORY;
1211         }
1212         object->OriginalIndex = Index;
1213         object->glIndex = -1;
1214
1215         /* Add it to the front of list with the idea that lights will be changed as needed 
1216            BUT after any lights currently assigned GL indexes                             */
1217         insertAt = This->stateBlock->lights;
1218         prevPos  = NULL;
1219         while (insertAt != NULL && insertAt->glIndex != -1) {
1220             prevPos  = insertAt;
1221             insertAt = insertAt->next;
1222         }
1223
1224         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1225             This->stateBlock->lights = object;
1226         } else if (insertAt == NULL) { /* End of list */
1227             prevPos->next = object;
1228             object->prev = prevPos;
1229         } else { /* Middle of chain */
1230             if (prevPos == NULL) {
1231                 This->stateBlock->lights = object;
1232             } else {
1233                 prevPos->next = object;
1234             }
1235             object->prev = prevPos;
1236             object->next = insertAt;
1237             insertAt->prev = object;
1238         }
1239     }
1240
1241     /* Initialze the object */
1242     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,
1243           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1244           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1245           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1246     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1247           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1248     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1249
1250     /* Save away the information */
1251     memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1252
1253     switch (pLight->Type) {
1254     case D3DLIGHT_POINT:
1255         /* Position */
1256         object->lightPosn[0] = pLight->Position.x;
1257         object->lightPosn[1] = pLight->Position.y;
1258         object->lightPosn[2] = pLight->Position.z;
1259         object->lightPosn[3] = 1.0f;
1260         object->cutoff = 180.0f;
1261         /* FIXME: Range */
1262         break;
1263
1264     case D3DLIGHT_DIRECTIONAL:
1265         /* Direction */
1266         object->lightPosn[0] = -pLight->Direction.x;
1267         object->lightPosn[1] = -pLight->Direction.y;
1268         object->lightPosn[2] = -pLight->Direction.z;
1269         object->lightPosn[3] = 0.0;
1270         object->exponent     = 0.0f;
1271         object->cutoff       = 180.0f;
1272         break;
1273
1274     case D3DLIGHT_SPOT:
1275         /* Position */
1276         object->lightPosn[0] = pLight->Position.x;
1277         object->lightPosn[1] = pLight->Position.y;
1278         object->lightPosn[2] = pLight->Position.z;
1279         object->lightPosn[3] = 1.0;
1280
1281         /* Direction */
1282         object->lightDirn[0] = pLight->Direction.x;
1283         object->lightDirn[1] = pLight->Direction.y;
1284         object->lightDirn[2] = pLight->Direction.z;
1285         object->lightDirn[3] = 1.0;
1286
1287         /*
1288          * opengl-ish and d3d-ish spot lights use too different models for the
1289          * light "intensity" as a function of the angle towards the main light direction,
1290          * so we only can approximate very roughly.
1291          * however spot lights are rather rarely used in games (if ever used at all).
1292          * furthermore if still used, probably nobody pays attention to such details.
1293          */
1294         if (pLight->Falloff == 0) {
1295             rho = 6.28f;
1296         } else {
1297             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1298         }
1299         if (rho < 0.0001) rho = 0.0001f;
1300         object->exponent = -0.3/log(cos(rho/2));
1301         object->cutoff = pLight->Phi*90/M_PI;
1302
1303         /* FIXME: Range */
1304         break;
1305
1306     default:
1307         FIXME("Unrecognized light type %d\n", pLight->Type);
1308     }
1309
1310     /* Update the live definitions if the light is currently assigned a glIndex */
1311     if (object->glIndex != -1) {
1312         setup_light(iface, object->glIndex, object);
1313     }
1314     return D3D_OK;
1315 }
1316
1317 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1318     PLIGHTINFOEL *lightInfo = NULL;
1319     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; 
1320     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1321     
1322     /* Locate the light in the live lights */
1323     lightInfo = This->stateBlock->lights;
1324     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1325
1326     if (lightInfo == NULL) {
1327         TRACE("Light information requested but light not defined\n");
1328         return D3DERR_INVALIDCALL;
1329     }
1330
1331     memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1332     return D3D_OK;
1333 }
1334
1335 /*****
1336  * Get / Set Light Enable 
1337  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1338  *****/
1339 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1340     PLIGHTINFOEL *lightInfo = NULL;
1341     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1342     TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1343
1344     /* If recording state block, just add to end of lights chain with changedEnable set to true */
1345     if (This->isRecordingState) {
1346         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1347         if (NULL == lightInfo) {
1348             return D3DERR_OUTOFVIDEOMEMORY;
1349         }
1350         lightInfo->OriginalIndex = Index;
1351         lightInfo->glIndex = -1;
1352         lightInfo->enabledChanged = TRUE;
1353
1354         /* Add to the END of the chain of lights changes to be replayed */
1355         if (This->updateStateBlock->lights == NULL) {
1356             This->updateStateBlock->lights = lightInfo;
1357         } else {
1358             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1359             while (temp->next != NULL) temp=temp->next;
1360             temp->next = lightInfo;
1361         }
1362         TRACE("Recording... not performing anything more\n");
1363         return D3D_OK;
1364     }
1365
1366     /* Not recording... So, locate the light in the live lights */
1367     lightInfo = This->stateBlock->lights;
1368     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1369
1370     /* Special case - enabling an undefined light creates one with a strict set of parms! */
1371     if (lightInfo == NULL) {
1372         D3DLIGHT9 lightParms;
1373         /* Warning - untested code :-) Prob safe to change fixme to a trace but
1374              wait until someone confirms it seems to work!                     */
1375         TRACE("Light enabled requested but light not defined, so defining one!\n"); 
1376         lightParms.Type = D3DLIGHT_DIRECTIONAL;
1377         lightParms.Diffuse.r = 1.0;
1378         lightParms.Diffuse.g = 1.0;
1379         lightParms.Diffuse.b = 1.0;
1380         lightParms.Diffuse.a = 0.0;
1381         lightParms.Specular.r = 0.0;
1382         lightParms.Specular.g = 0.0;
1383         lightParms.Specular.b = 0.0;
1384         lightParms.Specular.a = 0.0;
1385         lightParms.Ambient.r = 0.0;
1386         lightParms.Ambient.g = 0.0;
1387         lightParms.Ambient.b = 0.0;
1388         lightParms.Ambient.a = 0.0;
1389         lightParms.Position.x = 0.0;
1390         lightParms.Position.y = 0.0;
1391         lightParms.Position.z = 0.0;
1392         lightParms.Direction.x = 0.0;
1393         lightParms.Direction.y = 0.0;
1394         lightParms.Direction.z = 1.0;
1395         lightParms.Range = 0.0;
1396         lightParms.Falloff = 0.0;
1397         lightParms.Attenuation0 = 0.0;
1398         lightParms.Attenuation1 = 0.0;
1399         lightParms.Attenuation2 = 0.0;
1400         lightParms.Theta = 0.0;
1401         lightParms.Phi = 0.0;
1402         IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1403
1404         /* Search for it again! Should be fairly quick as near head of list */
1405         lightInfo = This->stateBlock->lights;
1406         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1407         if (lightInfo == NULL) {
1408             FIXME("Adding default lights has failed dismally\n");
1409             return D3DERR_INVALIDCALL;
1410         }
1411     }
1412
1413     /* OK, we now have a light... */
1414     if (Enable == FALSE) {
1415
1416         /* If we are disabling it, check it was enabled, and
1417            still only do something if it has assigned a glIndex (which it should have!)   */
1418         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1419             TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1420             ENTER_GL();
1421             glDisable(GL_LIGHT0 + lightInfo->glIndex);
1422             checkGLcall("glDisable GL_LIGHT0+Index");
1423             LEAVE_GL();
1424         } else {
1425             TRACE("Nothing to do as light was not enabled\n");
1426         }
1427         lightInfo->lightEnabled = FALSE;
1428     } else {
1429
1430         /* We are enabling it. If it is enabled, it's really simple */
1431         if (lightInfo->lightEnabled) {
1432             /* nop */
1433             TRACE("Nothing to do as light was enabled\n");
1434
1435         /* If it already has a glIndex, it's still simple */
1436         } else if (lightInfo->glIndex != -1) {
1437             TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1438             lightInfo->lightEnabled = TRUE;
1439             ENTER_GL();
1440             glEnable(GL_LIGHT0 + lightInfo->glIndex);
1441             checkGLcall("glEnable GL_LIGHT0+Index already setup");
1442             LEAVE_GL();
1443
1444         /* Otherwise got to find space - lights are ordered gl indexes first */
1445         } else {
1446             PLIGHTINFOEL *bsf  = NULL;
1447             PLIGHTINFOEL *pos  = This->stateBlock->lights;
1448             PLIGHTINFOEL *prev = NULL;
1449             int           Index= 0;
1450             int           glIndex = -1;
1451
1452             /* Try to minimize changes as much as possible */
1453             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1454
1455                 /* Try to remember which index can be replaced if necessary */
1456                 if (bsf==NULL && pos->lightEnabled == FALSE) {
1457                     /* Found a light we can replace, save as best replacement */
1458                     bsf = pos;
1459                 }
1460
1461                 /* Step to next space */
1462                 prev = pos;
1463                 pos = pos->next;
1464                 Index ++;
1465             }
1466
1467             /* If we have too many active lights, fail the call */
1468             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1469                 FIXME("Program requests too many concurrent lights\n");
1470                 return D3DERR_INVALIDCALL;
1471
1472             /* If we have allocated all lights, but not all are enabled,
1473                reuse one which is not enabled                           */
1474             } else if (Index == This->maxConcurrentLights) {
1475                 /* use bsf - Simply swap the new light and the BSF one */
1476                 PLIGHTINFOEL *bsfNext = bsf->next;
1477                 PLIGHTINFOEL *bsfPrev = bsf->prev;
1478
1479                 /* Sort out ends */
1480                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1481                 if (bsf->prev != NULL) {
1482                     bsf->prev->next = lightInfo;
1483                 } else {
1484                     This->stateBlock->lights = lightInfo;
1485                 }
1486
1487                 /* If not side by side, lots of chains to update */
1488                 if (bsf->next != lightInfo) {
1489                     lightInfo->prev->next = bsf;
1490                     bsf->next->prev = lightInfo;
1491                     bsf->next       = lightInfo->next;
1492                     bsf->prev       = lightInfo->prev;
1493                     lightInfo->next = bsfNext;
1494                     lightInfo->prev = bsfPrev;
1495
1496                 } else {
1497                     /* Simple swaps */
1498                     bsf->prev = lightInfo;
1499                     bsf->next = lightInfo->next;
1500                     lightInfo->next = bsf;
1501                     lightInfo->prev = bsfPrev;
1502                 }
1503
1504
1505                 /* Update states */
1506                 glIndex = bsf->glIndex;
1507                 bsf->glIndex = -1;
1508                 lightInfo->glIndex = glIndex;
1509                 lightInfo->lightEnabled = TRUE;
1510
1511                 /* Finally set up the light in gl itself */
1512                 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1513                 ENTER_GL();
1514                 setup_light(iface, glIndex, lightInfo);
1515                 glEnable(GL_LIGHT0 + glIndex);
1516                 checkGLcall("glEnable GL_LIGHT0 new setup");
1517                 LEAVE_GL();
1518
1519             /* If we reached the end of the allocated lights, with space in the
1520                gl lights, setup a new light                                     */
1521             } else if (pos->glIndex == -1) {
1522
1523                 /* We reached the end of the allocated gl lights, so already 
1524                     know the index of the next one!                          */
1525                 glIndex = Index;
1526                 lightInfo->glIndex = glIndex;
1527                 lightInfo->lightEnabled = TRUE;
1528
1529                 /* In an ideal world, it's already in the right place */
1530                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1531                    /* No need to move it */
1532                 } else {
1533                     /* Remove this light from the list */
1534                     lightInfo->prev->next = lightInfo->next;
1535                     if (lightInfo->next != NULL) {
1536                         lightInfo->next->prev = lightInfo->prev;
1537                     }
1538
1539                     /* Add in at appropriate place (inbetween prev and pos) */
1540                     lightInfo->prev = prev;
1541                     lightInfo->next = pos;
1542                     if (prev == NULL) {
1543                         This->stateBlock->lights = lightInfo;
1544                     } else {
1545                         prev->next = lightInfo;
1546                     }
1547                     if (pos != NULL) {
1548                         pos->prev = lightInfo;
1549                     }
1550                 }
1551
1552                 /* Finally set up the light in gl itself */
1553                 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1554                 ENTER_GL();
1555                 setup_light(iface, glIndex, lightInfo);
1556                 glEnable(GL_LIGHT0 + glIndex);
1557                 checkGLcall("glEnable GL_LIGHT0 new setup");
1558                 LEAVE_GL();
1559                 
1560             }
1561         }
1562     }
1563     return D3D_OK;
1564 }
1565
1566 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
1567
1568     PLIGHTINFOEL *lightInfo = NULL;
1569     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; 
1570     TRACE("(%p) : for idx(%ld)\n", This, Index);
1571     
1572     /* Locate the light in the live lights */
1573     lightInfo = This->stateBlock->lights;
1574     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1575
1576     if (lightInfo == NULL) {
1577         TRACE("Light enabled state requested but light not defined\n");
1578         return D3DERR_INVALIDCALL;
1579     }
1580     *pEnable = lightInfo->lightEnabled;
1581     return D3D_OK;
1582 }
1583
1584 /*****
1585  * Get / Set Clip Planes
1586  *****/
1587 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
1588     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1589     TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
1590
1591     /* Validate Index */
1592     if (Index >= GL_LIMITS(clipplanes)) {
1593         TRACE("Application has requested clipplane this device doesn't support\n");
1594         return D3DERR_INVALIDCALL;
1595     }
1596
1597     This->updateStateBlock->changed.clipplane[Index] = TRUE;
1598     This->updateStateBlock->set.clipplane[Index] = TRUE;
1599     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
1600     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
1601     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
1602     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
1603
1604     /* Handle recording of state blocks */
1605     if (This->isRecordingState) {
1606         TRACE("Recording... not performing anything\n");
1607         return D3D_OK;
1608     }
1609
1610     /* Apply it */
1611
1612     ENTER_GL();
1613
1614     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
1615     glMatrixMode(GL_MODELVIEW);
1616     glPushMatrix();
1617     glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1618
1619     TRACE("Clipplane [%f,%f,%f,%f]\n", 
1620           This->updateStateBlock->clipplane[Index][0], 
1621           This->updateStateBlock->clipplane[Index][1],
1622           This->updateStateBlock->clipplane[Index][2], 
1623           This->updateStateBlock->clipplane[Index][3]);
1624     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
1625     checkGLcall("glClipPlane");
1626
1627     glPopMatrix();
1628     LEAVE_GL();
1629
1630     return D3D_OK;
1631 }
1632
1633 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
1634     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1635     TRACE("(%p) : for idx %ld\n", This, Index);
1636
1637     /* Validate Index */
1638     if (Index >= GL_LIMITS(clipplanes)) {
1639         TRACE("Application has requested clipplane this device doesn't support\n");
1640         return D3DERR_INVALIDCALL;
1641     }
1642
1643     pPlane[0] = This->stateBlock->clipplane[Index][0];
1644     pPlane[1] = This->stateBlock->clipplane[Index][1];
1645     pPlane[2] = This->stateBlock->clipplane[Index][2];
1646     pPlane[3] = This->stateBlock->clipplane[Index][3];
1647     return D3D_OK;
1648 }
1649
1650 /*****
1651  * Get / Set Clip Plane Status
1652  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
1653  *****/
1654 HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
1655     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1656     FIXME("(%p) : stub\n", This);
1657     if (NULL == pClipStatus) {
1658       return D3DERR_INVALIDCALL;
1659     }
1660     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
1661     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
1662     return D3D_OK;
1663 }
1664
1665 HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
1666     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1667     FIXME("(%p) : stub\n", This);    
1668     if (NULL == pClipStatus) {
1669       return D3DERR_INVALIDCALL;
1670     }
1671     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
1672     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
1673     return D3D_OK;
1674 }
1675
1676 /*****
1677  * Get / Set Material
1678  *   WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
1679  *****/
1680 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
1681     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1682
1683     This->updateStateBlock->changed.material = TRUE;
1684     This->updateStateBlock->set.material = TRUE;
1685     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
1686
1687     /* Handle recording of state blocks */
1688     if (This->isRecordingState) {
1689         TRACE("Recording... not performing anything\n");
1690         return D3D_OK;
1691     }
1692
1693     ENTER_GL();
1694     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1695     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1696     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1697     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1698     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1699
1700     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
1701     checkGLcall("glMaterialfv");
1702     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
1703     checkGLcall("glMaterialfv");
1704
1705     /* Only change material color if specular is enabled, otherwise it is set to black */
1706     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1707        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1708        checkGLcall("glMaterialfv");
1709     } else {
1710        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1711        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1712        checkGLcall("glMaterialfv");
1713     }
1714     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
1715     checkGLcall("glMaterialfv");
1716     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
1717     checkGLcall("glMaterialf");
1718
1719     LEAVE_GL();
1720     return D3D_OK;
1721 }
1722
1723 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
1724     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1725     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
1726     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1727     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1728     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1729     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1730     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1731     return D3D_OK;
1732 }
1733
1734 /*****
1735  * Get / Set Indices
1736  *****/
1737 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData, 
1738                                              UINT BaseVertexIndex) {
1739     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
1740     IWineD3DIndexBuffer *oldIdxs;
1741
1742     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
1743     oldIdxs = This->updateStateBlock->pIndexData;
1744
1745     This->updateStateBlock->changed.indices = TRUE;
1746     This->updateStateBlock->set.indices = TRUE;
1747     This->updateStateBlock->pIndexData = pIndexData;
1748     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
1749
1750     /* Handle recording of state blocks */
1751     if (This->isRecordingState) {
1752         TRACE("Recording... not performing anything\n");
1753         return D3D_OK;
1754     }
1755
1756     if (oldIdxs)    IWineD3DIndexBuffer_Release(oldIdxs);
1757     if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
1758     return D3D_OK;
1759 }
1760
1761 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
1762     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1763
1764     *ppIndexData = This->stateBlock->pIndexData;
1765     
1766     /* up ref count on ppindexdata */
1767     if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
1768     *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
1769
1770     return D3D_OK;
1771 }
1772
1773 /*****
1774  * Get / Set Viewports
1775  *****/
1776 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
1777     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1778
1779     TRACE("(%p)\n", This);
1780     This->updateStateBlock->changed.viewport = TRUE;
1781     This->updateStateBlock->set.viewport = TRUE;
1782     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
1783
1784     /* Handle recording of state blocks */
1785     if (This->isRecordingState) {
1786         TRACE("Recording... not performing anything\n");
1787         return D3D_OK;
1788     }
1789
1790     ENTER_GL();
1791
1792     TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1793           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1794
1795     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1796     checkGLcall("glDepthRange");
1797     /* Note: GL requires lower left, DirectX supplies upper left */
1798     /* TODO: replace usage of renderTarget with context management */
1799     glViewport(pViewport->X, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)), 
1800                     pViewport->Width, pViewport->Height);
1801     checkGLcall("glViewport");
1802
1803     LEAVE_GL();
1804
1805     return D3D_OK;
1806
1807 }
1808
1809 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
1810     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1811     TRACE("(%p)\n", This);
1812     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
1813     return D3D_OK;
1814 }
1815
1816 /*****
1817  * Get / Set Render States
1818  * TODO: Verify against dx9 definitions
1819  *****/
1820 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
1821
1822     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
1823     DWORD                OldValue = This->stateBlock->renderState[State];
1824     
1825     /* Simple way of referring to either a DWORD or a 4 byte float */
1826     union {
1827         DWORD d;
1828         float f;
1829     } tmpvalue;
1830         
1831     TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
1832     This->updateStateBlock->changed.renderState[State] = TRUE;
1833     This->updateStateBlock->set.renderState[State] = TRUE;
1834     This->updateStateBlock->renderState[State] = Value;
1835
1836     /* Handle recording of state blocks */
1837     if (This->isRecordingState) {
1838         TRACE("Recording... not performing anything\n");
1839         return D3D_OK;
1840     }
1841
1842     ENTER_GL();
1843
1844     switch (State) {
1845     case WINED3DRS_FILLMODE                  :
1846         switch ((D3DFILLMODE) Value) {
1847         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1848         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1849         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1850         default:
1851             FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
1852         }
1853         checkGLcall("glPolygonMode (fillmode)");
1854         break;
1855
1856     case WINED3DRS_LIGHTING                  :
1857         if (Value) {
1858             glEnable(GL_LIGHTING);
1859             checkGLcall("glEnable GL_LIGHTING");
1860         } else {
1861             glDisable(GL_LIGHTING);
1862             checkGLcall("glDisable GL_LIGHTING");
1863         }
1864         break;
1865
1866     case WINED3DRS_ZENABLE                   :
1867         switch ((D3DZBUFFERTYPE) Value) {
1868         case D3DZB_FALSE:
1869             glDisable(GL_DEPTH_TEST);
1870             checkGLcall("glDisable GL_DEPTH_TEST");
1871             break;
1872         case D3DZB_TRUE:
1873             glEnable(GL_DEPTH_TEST);
1874             checkGLcall("glEnable GL_DEPTH_TEST");
1875             break;
1876         case D3DZB_USEW:
1877             glEnable(GL_DEPTH_TEST);
1878             checkGLcall("glEnable GL_DEPTH_TEST");
1879             FIXME("W buffer is not well handled\n");
1880             break;
1881         default:
1882             FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
1883         }
1884         break;
1885
1886     case WINED3DRS_CULLMODE                  :
1887
1888         /* If we are culling "back faces with clockwise vertices" then
1889            set front faces to be counter clockwise and enable culling  
1890            of back faces                                               */
1891         switch ((D3DCULL) Value) {
1892         case D3DCULL_NONE:
1893             glDisable(GL_CULL_FACE);
1894             checkGLcall("glDisable GL_CULL_FACE");
1895             break;
1896         case D3DCULL_CW:
1897             glEnable(GL_CULL_FACE);
1898             checkGLcall("glEnable GL_CULL_FACE");
1899             if (This->renderUpsideDown) {
1900                 glFrontFace(GL_CW);
1901                 checkGLcall("glFrontFace GL_CW");
1902             } else {
1903                 glFrontFace(GL_CCW);
1904                 checkGLcall("glFrontFace GL_CCW");
1905             }
1906             glCullFace(GL_BACK);
1907             break;
1908         case D3DCULL_CCW:
1909             glEnable(GL_CULL_FACE);
1910             checkGLcall("glEnable GL_CULL_FACE");
1911             if (This->renderUpsideDown) {
1912                 glFrontFace(GL_CCW); 
1913                 checkGLcall("glFrontFace GL_CCW");
1914             } else {
1915                 glFrontFace(GL_CW);
1916                 checkGLcall("glFrontFace GL_CW");
1917             }
1918             glCullFace(GL_BACK);
1919             break;
1920         default:
1921             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
1922         }
1923         break;
1924
1925     case WINED3DRS_SHADEMODE                 :
1926         switch ((D3DSHADEMODE) Value) {
1927         case D3DSHADE_FLAT:
1928             glShadeModel(GL_FLAT);
1929             checkGLcall("glShadeModel");
1930             break;
1931         case D3DSHADE_GOURAUD:
1932             glShadeModel(GL_SMOOTH);
1933             checkGLcall("glShadeModel");
1934             break;
1935         case D3DSHADE_PHONG:
1936             FIXME("D3DSHADE_PHONG isn't supported?\n");
1937
1938             LEAVE_GL();
1939             return D3DERR_INVALIDCALL;
1940         default:
1941             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
1942         }
1943         break;
1944
1945     case WINED3DRS_DITHERENABLE              :
1946         if (Value) {
1947             glEnable(GL_DITHER);
1948             checkGLcall("glEnable GL_DITHER");
1949         } else {
1950             glDisable(GL_DITHER);
1951             checkGLcall("glDisable GL_DITHER");
1952         }
1953         break;
1954
1955     case WINED3DRS_ZWRITEENABLE              :
1956         if (Value) {
1957             glDepthMask(1);
1958             checkGLcall("glDepthMask");
1959         } else {
1960             glDepthMask(0);
1961             checkGLcall("glDepthMask");
1962         }
1963         break;
1964
1965     case WINED3DRS_ZFUNC                     :
1966         {
1967             int glParm = GL_LESS;
1968
1969             switch ((D3DCMPFUNC) Value) {
1970             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
1971             case D3DCMP_LESS:          glParm=GL_LESS; break;
1972             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
1973             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
1974             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
1975             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
1976             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
1977             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
1978             default:
1979                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1980             }
1981             glDepthFunc(glParm);
1982             checkGLcall("glDepthFunc");
1983         }
1984         break;
1985
1986     case WINED3DRS_AMBIENT                   :
1987         {
1988             float col[4];
1989             D3DCOLORTOGLFLOAT4(Value, col);
1990             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
1991             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
1992             checkGLcall("glLightModel for MODEL_AMBIENT");
1993
1994         }
1995         break;
1996
1997     case WINED3DRS_ALPHABLENDENABLE          :
1998         if (Value) {
1999             glEnable(GL_BLEND);
2000             checkGLcall("glEnable GL_BLEND");
2001         } else {
2002             glDisable(GL_BLEND);
2003             checkGLcall("glDisable GL_BLEND");
2004         };
2005         break;
2006
2007     case WINED3DRS_SRCBLEND                  :
2008     case WINED3DRS_DESTBLEND                 :
2009         {
2010             int newVal = GL_ZERO;
2011             switch (Value) {
2012             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
2013             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
2014             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
2015             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
2016             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
2017             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
2018             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
2019             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
2020             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
2021             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
2022             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
2023
2024             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
2025                 This->srcBlend = newVal;
2026                 This->dstBlend = newVal;
2027                 break;
2028
2029             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
2030                 This->srcBlend = newVal;
2031                 This->dstBlend = newVal;
2032                 break;
2033             default:
2034                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2035             }
2036
2037             if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2038             if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2039             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2040             glBlendFunc(This->srcBlend, This->dstBlend);
2041
2042             checkGLcall("glBlendFunc");
2043         }
2044         break;
2045
2046     case WINED3DRS_ALPHATESTENABLE           :
2047         if (Value) {
2048             glEnable(GL_ALPHA_TEST);
2049             checkGLcall("glEnable GL_ALPHA_TEST");
2050         } else {
2051             glDisable(GL_ALPHA_TEST);
2052             checkGLcall("glDisable GL_ALPHA_TEST");
2053         }
2054         break;
2055
2056     case WINED3DRS_ALPHAFUNC                 :
2057         {
2058             int glParm = GL_LESS;
2059             float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2060
2061             switch ((D3DCMPFUNC) Value) {
2062             case D3DCMP_NEVER:         glParm = GL_NEVER; break;
2063             case D3DCMP_LESS:          glParm = GL_LESS; break;
2064             case D3DCMP_EQUAL:         glParm = GL_EQUAL; break;
2065             case D3DCMP_LESSEQUAL:     glParm = GL_LEQUAL; break;
2066             case D3DCMP_GREATER:       glParm = GL_GREATER; break;
2067             case D3DCMP_NOTEQUAL:      glParm = GL_NOTEQUAL; break;
2068             case D3DCMP_GREATEREQUAL:  glParm = GL_GEQUAL; break;
2069             case D3DCMP_ALWAYS:        glParm = GL_ALWAYS; break;
2070             default:
2071                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2072             }
2073             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2074             glAlphaFunc(glParm, ref);
2075             This->alphafunc = glParm;
2076             checkGLcall("glAlphaFunc");
2077         }
2078         break;
2079
2080     case WINED3DRS_ALPHAREF                  :
2081         {
2082             int glParm = This->alphafunc;
2083             float ref = 1.0f;
2084
2085             ref = ((float) Value) / 255.0f;
2086             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2087             glAlphaFunc(glParm, ref);
2088             checkGLcall("glAlphaFunc");
2089         }
2090         break;
2091
2092     case WINED3DRS_CLIPPLANEENABLE           :
2093     case WINED3DRS_CLIPPING                  :
2094         {
2095             /* Ensure we only do the changed clip planes */
2096             DWORD enable  = 0xFFFFFFFF;
2097             DWORD disable = 0x00000000;
2098             
2099             /* If enabling / disabling all */
2100             if (State == WINED3DRS_CLIPPING) {
2101                 if (Value) {
2102                     enable  = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2103                     disable = 0x00;
2104                 } else {
2105                     disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2106                     enable  = 0x00;
2107                 }
2108             } else {
2109                 enable =   Value & ~OldValue;
2110                 disable = ~Value &  OldValue;
2111             }
2112             
2113             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
2114             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
2115             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
2116             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
2117             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
2118             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
2119             
2120             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2121             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2122             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2123             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2124             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2125             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2126
2127             /** update clipping status */
2128             if (enable) {
2129               This->stateBlock->clip_status.ClipUnion = 0;
2130               This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2131             } else {
2132               This->stateBlock->clip_status.ClipUnion = 0;
2133               This->stateBlock->clip_status.ClipIntersection = 0;
2134             }
2135         }
2136         break;
2137
2138     case WINED3DRS_BLENDOP                   :
2139         {
2140             int glParm = GL_FUNC_ADD;
2141
2142             switch ((D3DBLENDOP) Value) {
2143             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
2144             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
2145             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2146             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
2147             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
2148             default:
2149                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2150             }
2151             TRACE("glBlendEquation(%x)\n", glParm);
2152             glBlendEquation(glParm);
2153             checkGLcall("glBlendEquation");
2154         }
2155         break;
2156
2157     case WINED3DRS_TEXTUREFACTOR             :
2158         {
2159             unsigned int i;
2160
2161             /* Note the texture color applies to all textures whereas 
2162                GL_TEXTURE_ENV_COLOR applies to active only */
2163             float col[4];
2164             D3DCOLORTOGLFLOAT4(Value, col);
2165             /* Set the default alpha blend color */
2166             glBlendColor(col[0], col[1], col[2], col[3]);
2167             checkGLcall("glBlendColor");
2168
2169             /* And now the default texture color as well */
2170             for (i = 0; i < GL_LIMITS(textures); i++) {
2171
2172                 /* Note the D3DRS value applies to all textures, but GL has one
2173                    per texture, so apply it now ready to be used!               */
2174                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2175                     GLACTIVETEXTURE(i);
2176                 } else if (i>0) {
2177                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2178                 }
2179
2180                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2181                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2182             }
2183         }
2184         break;
2185
2186     case WINED3DRS_SPECULARENABLE            :
2187         {
2188             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2189                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2190                specular color. This is wrong:
2191                Separate specular color means the specular colour is maintained separately, whereas
2192                single color means it is merged in. However in both cases they are being used to
2193                some extent.
2194                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2195                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2196                   running 1.4 yet!
2197              */
2198               if (Value) {
2199                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2200                 checkGLcall("glMaterialfv");
2201                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2202                   glEnable(GL_COLOR_SUM_EXT);
2203                 } else {
2204                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
2205                 }
2206                 checkGLcall("glEnable(GL_COLOR_SUM)");
2207               } else {
2208                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2209
2210                 /* for the case of enabled lighting: */
2211                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2212                 checkGLcall("glMaterialfv");
2213
2214                 /* for the case of disabled lighting: */
2215                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2216                   glDisable(GL_COLOR_SUM_EXT);
2217                 } else {
2218                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
2219                 }
2220                 checkGLcall("glDisable(GL_COLOR_SUM)");
2221               }
2222         }
2223         break;
2224
2225     case WINED3DRS_STENCILENABLE             :
2226         if (Value) {
2227             glEnable(GL_STENCIL_TEST);
2228             checkGLcall("glEnable GL_STENCIL_TEST");
2229         } else {
2230             glDisable(GL_STENCIL_TEST);
2231             checkGLcall("glDisable GL_STENCIL_TEST");
2232         }
2233         break;
2234
2235     case WINED3DRS_STENCILFUNC               :
2236         {
2237            int glParm = GL_ALWAYS;
2238            int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2239            GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2240
2241            switch ((D3DCMPFUNC) Value) {
2242            case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2243            case D3DCMP_LESS:          glParm=GL_LESS; break;
2244            case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2245            case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2246            case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2247            case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2248            case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2249            case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2250            default:
2251                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2252            }
2253            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2254            This->stencilfunc = glParm;
2255            glStencilFunc(glParm, ref, mask);
2256            checkGLcall("glStencilFunc");
2257         }
2258         break;
2259
2260     case WINED3DRS_STENCILREF                :
2261         {
2262            int glParm = This->stencilfunc;
2263            int ref = 0;
2264            GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2265
2266            ref = Value;
2267            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2268            glStencilFunc(glParm, ref, mask);
2269            checkGLcall("glStencilFunc");
2270         }
2271         break;
2272
2273     case WINED3DRS_STENCILMASK               :
2274         {
2275            int glParm = This->stencilfunc;
2276            int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2277            GLuint mask = Value;
2278
2279            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2280            glStencilFunc(glParm, ref, mask);
2281            checkGLcall("glStencilFunc");
2282         }
2283         break;
2284
2285     case WINED3DRS_STENCILFAIL               :
2286         {
2287             GLenum fail  ; 
2288             GLenum zpass ; 
2289             GLenum zfail ; 
2290
2291             fail = StencilOp(Value);
2292             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2293             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2294             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2295             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2296
2297             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2298             glStencilOp(fail, zfail, zpass);
2299             checkGLcall("glStencilOp(fail, zfail, zpass);");
2300         }
2301         break;
2302     case WINED3DRS_STENCILZFAIL              :
2303         {
2304             GLenum fail  ; 
2305             GLenum zpass ; 
2306             GLenum zfail ; 
2307
2308             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2309             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2310             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2311             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2312             zfail = StencilOp(Value);
2313
2314             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2315             glStencilOp(fail, zfail, zpass);
2316             checkGLcall("glStencilOp(fail, zfail, zpass);");
2317         }
2318         break;
2319     case WINED3DRS_STENCILPASS               :
2320         {
2321             GLenum fail  ; 
2322             GLenum zpass ; 
2323             GLenum zfail ; 
2324
2325             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2326             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2327             zpass = StencilOp(Value);
2328             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2329             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2330
2331             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2332             glStencilOp(fail, zfail, zpass);
2333             checkGLcall("glStencilOp(fail, zfail, zpass);");
2334         }
2335         break;
2336
2337     case WINED3DRS_STENCILWRITEMASK          :
2338         {
2339             glStencilMask(Value);
2340             TRACE("glStencilMask(%lu)\n", Value);
2341             checkGLcall("glStencilMask");
2342         }
2343         break;
2344
2345     case WINED3DRS_FOGENABLE                 :
2346         {
2347           if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2348                glEnable(GL_FOG);
2349                checkGLcall("glEnable GL_FOG");
2350             } else {
2351                glDisable(GL_FOG);
2352                checkGLcall("glDisable GL_FOG");
2353             }
2354         }
2355         break;
2356
2357     case WINED3DRS_RANGEFOGENABLE            :
2358         {
2359             if (Value) {
2360               TRACE("Enabled RANGEFOG");
2361             } else {
2362               TRACE("Disabled RANGEFOG");
2363             }
2364         }
2365         break;
2366
2367     case WINED3DRS_FOGCOLOR                  :
2368         {
2369             float col[4];
2370             D3DCOLORTOGLFLOAT4(Value, col);
2371             /* Set the default alpha blend color */
2372             glFogfv(GL_FOG_COLOR, &col[0]);
2373             checkGLcall("glFog GL_FOG_COLOR");
2374         }
2375         break;
2376
2377     case WINED3DRS_FOGTABLEMODE              :
2378         { 
2379           glHint(GL_FOG_HINT, GL_NICEST);
2380           switch (Value) {
2381           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2382           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2383           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2384           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2385           default:
2386             FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2387           }
2388           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2389             glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2390           }
2391         }
2392         break;
2393
2394     case WINED3DRS_FOGVERTEXMODE             :
2395         { 
2396           glHint(GL_FOG_HINT, GL_FASTEST);
2397           switch (Value) {
2398           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2399           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break; 
2400           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break; 
2401           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break; 
2402           default:
2403             FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2404           }
2405           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2406             glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2407           }
2408         }
2409         break;
2410
2411     case WINED3DRS_FOGSTART                  :
2412         {
2413             tmpvalue.d = Value;
2414             glFogfv(GL_FOG_START, &tmpvalue.f);
2415             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2416             TRACE("Fog Start == %f\n", tmpvalue.f);
2417         }
2418         break;
2419
2420     case WINED3DRS_FOGEND                    :
2421         {
2422             tmpvalue.d = Value;
2423             glFogfv(GL_FOG_END, &tmpvalue.f);
2424             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2425             TRACE("Fog End == %f\n", tmpvalue.f);
2426         }
2427         break;
2428
2429     case WINED3DRS_FOGDENSITY                :
2430         {
2431             tmpvalue.d = Value;
2432             glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2433             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2434         }
2435         break;
2436
2437     case WINED3DRS_VERTEXBLEND               :
2438         {
2439           This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2440           TRACE("Vertex Blending state to %ld\n",  Value);
2441         }
2442         break;
2443
2444     case WINED3DRS_TWEENFACTOR               :
2445         {
2446           tmpvalue.d = Value;
2447           This->updateStateBlock->tween_factor = tmpvalue.f;
2448           TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2449         }
2450         break;
2451
2452     case WINED3DRS_INDEXEDVERTEXBLENDENABLE  :
2453         {
2454           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2455         }
2456         break;
2457
2458     case WINED3DRS_COLORVERTEX               :
2459     case WINED3DRS_DIFFUSEMATERIALSOURCE     :
2460     case WINED3DRS_SPECULARMATERIALSOURCE    :
2461     case WINED3DRS_AMBIENTMATERIALSOURCE     :
2462     case WINED3DRS_EMISSIVEMATERIALSOURCE    :
2463         {
2464             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2465
2466             if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
2467                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2468                       This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
2469                       This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
2470                       This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
2471                       This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
2472
2473                 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2474                     if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2475                         Parm = GL_AMBIENT_AND_DIFFUSE;
2476                     } else {
2477                         Parm = GL_DIFFUSE;
2478                     }
2479                 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2480                     Parm = GL_AMBIENT;
2481                 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2482                     Parm = GL_EMISSION;
2483                 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2484                     Parm = GL_SPECULAR;
2485                 } else {
2486                     Parm = -1;
2487                 }
2488
2489                 if (Parm == -1) {
2490                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2491                 } else {
2492                     This->tracking_color = NEEDS_TRACKING;
2493                     This->tracking_parm  = Parm;
2494                 }
2495
2496             } else {
2497                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2498             }
2499         }
2500         break; 
2501
2502     case WINED3DRS_LINEPATTERN               :
2503         {
2504             union {
2505                 DWORD                 d;
2506                 D3DLINEPATTERN        lp;
2507             } tmppattern;
2508             tmppattern.d = Value;
2509
2510             TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2511
2512             if (tmppattern.lp.wRepeatFactor) {
2513                 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2514                 checkGLcall("glLineStipple(repeat, linepattern)");
2515                 glEnable(GL_LINE_STIPPLE);
2516                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2517             } else {
2518                 glDisable(GL_LINE_STIPPLE);
2519                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2520             }
2521         }
2522         break;
2523
2524     case WINED3DRS_ZBIAS                     :
2525         {
2526             if (Value) {
2527                 tmpvalue.d = Value;
2528                 TRACE("ZBias value %f\n", tmpvalue.f);
2529                 glPolygonOffset(0, -tmpvalue.f);
2530                 checkGLcall("glPolygonOffset(0, -Value)");
2531                 glEnable(GL_POLYGON_OFFSET_FILL);
2532                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2533                 glEnable(GL_POLYGON_OFFSET_LINE);
2534                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2535                 glEnable(GL_POLYGON_OFFSET_POINT);
2536                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2537             } else {
2538                 glDisable(GL_POLYGON_OFFSET_FILL);
2539                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2540                 glDisable(GL_POLYGON_OFFSET_LINE);
2541                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2542                 glDisable(GL_POLYGON_OFFSET_POINT);
2543                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2544             }
2545         }
2546         break;
2547
2548     case WINED3DRS_NORMALIZENORMALS          :
2549         if (Value) {
2550             glEnable(GL_NORMALIZE);
2551             checkGLcall("glEnable(GL_NORMALIZE);");
2552         } else {
2553             glDisable(GL_NORMALIZE);
2554             checkGLcall("glDisable(GL_NORMALIZE);");
2555         }
2556         break;
2557
2558     case WINED3DRS_POINTSIZE                 :
2559         tmpvalue.d = Value;
2560         TRACE("Set point size to %f\n", tmpvalue.f);
2561         glPointSize(tmpvalue.f);
2562         checkGLcall("glPointSize(...);");
2563         break;
2564
2565     case WINED3DRS_POINTSIZE_MIN             :
2566         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2567           tmpvalue.d = Value;
2568           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2569           checkGLcall("glPointParameterfEXT(...);");
2570         } else {
2571           FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
2572         }
2573         break;
2574
2575     case WINED3DRS_POINTSIZE_MAX             :
2576         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2577           tmpvalue.d = Value;
2578           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2579           checkGLcall("glPointParameterfEXT(...);");
2580         } else {
2581           FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
2582         }
2583         break;
2584
2585     case WINED3DRS_POINTSCALE_A              :
2586     case WINED3DRS_POINTSCALE_B              :
2587     case WINED3DRS_POINTSCALE_C              :
2588     case WINED3DRS_POINTSCALEENABLE          :
2589         {
2590             /* If enabled, supply the parameters, otherwise fall back to defaults */
2591             if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
2592                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2593                 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
2594                 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
2595                 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
2596
2597                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2598                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2599                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2600                 } else {
2601                   TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
2602                 }
2603             } else {
2604                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2605                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2606                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2607                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2608                 } else {
2609                   TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
2610                 }
2611             }
2612             break;
2613         }
2614
2615     case WINED3DRS_COLORWRITEENABLE          :
2616       {
2617         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n", 
2618               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
2619               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2620               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
2621               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0); 
2622         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE, 
2623                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2624                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE, 
2625                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2626         checkGLcall("glColorMask(...)");
2627       }
2628       break;
2629
2630     case WINED3DRS_LOCALVIEWER               :
2631       {
2632         GLint state = (Value) ? 1 : 0;
2633         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);        
2634         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2635       }
2636       break;
2637
2638     case WINED3DRS_LASTPIXEL                 :
2639       {
2640         if (Value) {
2641           TRACE("Last Pixel Drawing Enabled\n");  
2642         } else {
2643           FIXME("Last Pixel Drawing Disabled, not handled yet\n");  
2644         }
2645       }
2646       break;
2647
2648     case WINED3DRS_SOFTWAREVERTEXPROCESSING  :
2649       {
2650         if (Value) {
2651           TRACE("Software Processing Enabled\n");  
2652         } else {
2653           TRACE("Software Processing Disabled\n");  
2654         }
2655       }
2656       break;
2657
2658       /** not supported */
2659     case WINED3DRS_ZVISIBLE                  :
2660       {
2661         LEAVE_GL();
2662         return D3DERR_INVALIDCALL;
2663       }
2664
2665         /* Unhandled yet...! */
2666     case WINED3DRS_EDGEANTIALIAS             :
2667     case WINED3DRS_WRAP0                     :
2668     case WINED3DRS_WRAP1                     :
2669     case WINED3DRS_WRAP2                     :
2670     case WINED3DRS_WRAP3                     :
2671     case WINED3DRS_WRAP4                     :
2672     case WINED3DRS_WRAP5                     :
2673     case WINED3DRS_WRAP6                     :
2674     case WINED3DRS_WRAP7                     :
2675     case WINED3DRS_POINTSPRITEENABLE         :
2676     case WINED3DRS_MULTISAMPLEANTIALIAS      :
2677     case WINED3DRS_MULTISAMPLEMASK           :
2678     case WINED3DRS_PATCHEDGESTYLE            :
2679     case WINED3DRS_PATCHSEGMENTS             :
2680     case WINED3DRS_DEBUGMONITORTOKEN         :
2681     case WINED3DRS_POSITIONORDER             :
2682     case WINED3DRS_NORMALORDER               :
2683         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2684         FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2685         break;
2686     default:
2687         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2688     }
2689
2690     LEAVE_GL();
2691
2692     return D3D_OK;
2693 }
2694
2695 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
2696     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2697     TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
2698     *pValue = This->stateBlock->renderState[State];
2699     return D3D_OK;
2700 }
2701
2702 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value){
2703     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2704
2705     FIXME("(%p) : stub\n", This);
2706     return D3D_OK;
2707 }
2708
2709 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value){
2710     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2711
2712     FIXME("(%p) : stub\n", This);
2713     return D3D_OK;
2714
2715 }
2716
2717 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect){ 
2718     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2719     ENTER_GL();
2720     
2721     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
2722     TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2723     glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
2724     LEAVE_GL();
2725     return D3D_OK;
2726 }
2727
2728 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect){ 
2729     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2730     GLint scissorBox[4];
2731
2732     ENTER_GL();
2733     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
2734     glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
2735     pRect->left = scissorBox[1];
2736     pRect->top = scissorBox[2];
2737     pRect->right = scissorBox[1] + scissorBox[3];
2738     pRect->bottom = scissorBox[2] + scissorBox[4]; 
2739     TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2740     LEAVE_GL();
2741     return D3D_OK;
2742 }
2743
2744 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
2745     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;   
2746     
2747     TRACE("(%p) : pDecl=%p\n", This, pDecl);
2748
2749     IWineD3DVertexDeclaration_AddRef(pDecl);
2750     if (NULL != This->updateStateBlock->vertexDecl) {
2751       IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
2752     }
2753     This->updateStateBlock->vertexDecl = pDecl;
2754     This->updateStateBlock->changed.vertexDecl = TRUE;
2755     This->updateStateBlock->set.vertexDecl = TRUE;
2756     return D3D_OK;
2757 }
2758
2759 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
2760     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2761
2762     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
2763     
2764     *ppDecl = This->updateStateBlock->vertexDecl;
2765     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
2766     return D3D_OK;
2767 }
2768
2769 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader){
2770     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2771
2772     static BOOL showFixmes = TRUE;
2773     
2774     This->updateStateBlock->vertexShader = pShader;
2775     This->updateStateBlock->changed.vertexShader = TRUE;
2776     This->updateStateBlock->set.vertexShader = TRUE;
2777     
2778     if(pShader == NULL){
2779     /* clear down the shader */
2780         TRACE("Clear down the shader\n");
2781     }else{
2782         if(showFixmes){
2783             FIXME("(%p) : stub pShader(%p)\n", This, pShader);
2784             showFixmes = FALSE;
2785         }
2786     }
2787
2788     return D3D_OK;
2789     
2790     /** FIXME: refernece counting? **/
2791     if (pShader  == NULL) { /* only valid with non FVF shaders */
2792       TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
2793       This->updateStateBlock->vertexShader = NULL;
2794     } else {
2795        TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
2796       This->updateStateBlock->vertexShader = pShader;
2797     }
2798     
2799     This->updateStateBlock->changed.vertexShader = TRUE;
2800     This->updateStateBlock->set.vertexShader = TRUE;
2801     
2802     /* Handle recording of state blocks */
2803     if (This->isRecordingState) {
2804       TRACE("Recording... not performing anything\n");
2805       return D3D_OK;
2806     }
2807     /**
2808      * TODO: merge HAL shaders context switching from prototype
2809      */
2810     return D3D_OK;
2811     
2812 }
2813
2814 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader){
2815     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2816     *ppShader = This->stateBlock->vertexShader;
2817     if(*ppShader != NULL)
2818         IWineD3DVertexShader_AddRef(*ppShader);
2819     TRACE("(%p) : returning %p\n", This, *ppShader);
2820     return D3D_OK;
2821 }
2822
2823 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL  *pConstantData, UINT BoolCount){
2824     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2825     
2826     TRACE("(%p) : stub\n", This);
2827     return D3D_OK;
2828 }
2829
2830 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL        *pConstantData, UINT BoolCount){
2831     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2832     TRACE("(%p) : stub\n", This);
2833     return D3D_OK;
2834 }
2835
2836 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int   *pConstantData, UINT Vector4iCount){
2837     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2838     TRACE("(%p) : stub\n", This);
2839     return D3D_OK;
2840 }
2841
2842 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int         *pConstantData, UINT Vector4iCount){
2843     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2844     TRACE("(%p) : stub\n", This);
2845     return D3D_OK;
2846 }
2847
2848 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
2849     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2850     TRACE("(%p) : stub\n", This);
2851     return D3D_OK;
2852 }
2853
2854 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float       *pConstantData, UINT Vector4fCount){    
2855     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2856     TRACE("(%p) : stub\n", This);
2857     return D3D_OK;
2858 }
2859
2860 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader  *pShader){
2861     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2862     TRACE("(%p) : stub\n", This);
2863     return D3D_OK;
2864 }
2865
2866 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader){
2867     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2868     TRACE("(%p) : stub\n", This);
2869     return D3D_OK;
2870 }
2871
2872
2873 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL   *pConstantData, UINT BoolCount){
2874     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2875     TRACE("(%p) : stub\n", This);
2876     return D3D_OK;
2877 }
2878
2879 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL         *pConstantData, UINT BoolCount){
2880     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2881     TRACE("(%p) : stub\n", This);
2882     return D3D_OK;
2883 }
2884
2885 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int    *pConstantData, UINT Vector4iCount){
2886     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2887     TRACE("(%p) : stub\n", This);
2888     return D3D_OK;
2889 }
2890
2891 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int          *pConstantData, UINT Vector4iCount){
2892     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2893     TRACE("(%p) : stub\n", This);
2894     return D3D_OK;
2895 }
2896
2897 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float  *pConstantData, UINT Vector4fCount){
2898     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2899     TRACE("(%p) : stub\n", This);
2900     return D3D_OK;
2901 }
2902
2903 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float        *pConstantData, UINT Vector4fCount){
2904     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2905     TRACE("(%p) : stub\n", This);
2906     return D3D_OK;
2907 }
2908
2909 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags){
2910     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2911     FIXME("(%p) : stub\n", This);
2912     return D3D_OK;
2913 }
2914
2915 /*****
2916  * Get / Set Texture Stage States
2917  * TODO: Verify against dx9 definitions
2918  *****/
2919 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
2920     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2921     union {
2922         float f;
2923         DWORD d;
2924     } tmpvalue;
2925
2926     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
2927    
2928     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
2929
2930     /* Reject invalid texture units */
2931     if (Stage >= GL_LIMITS(textures)) {
2932         TRACE("Attempt to access invalid texture rejected\n");
2933         return D3DERR_INVALIDCALL;
2934     }
2935
2936     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
2937     This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
2938     This->updateStateBlock->textureState[Stage][Type] = Value;
2939
2940     /* Handle recording of state blocks */
2941     if (This->isRecordingState) {
2942         TRACE("Recording... not performing anything\n");
2943         return D3D_OK;
2944     }
2945
2946     ENTER_GL();
2947
2948     /* Make appropriate texture active */
2949     VTRACE(("Activating appropriate texture state %ld\n", Stage));
2950     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2951         GLACTIVETEXTURE(Stage);
2952     } else if (Stage > 0) {
2953         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2954     }
2955
2956     switch (Type) {
2957
2958     case D3DTSS_MINFILTER             :
2959     case D3DTSS_MIPFILTER             :
2960         {
2961             DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
2962             DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
2963             GLint realVal = GL_LINEAR;
2964
2965             if (ValueMIN == D3DTEXF_NONE) {
2966               /* Doesn't really make sense - Windows just seems to disable
2967                  mipmapping when this occurs                              */
2968               FIXME("Odd - minfilter of none, just disabling mipmaps\n");
2969               realVal = GL_LINEAR;
2970             } else if (ValueMIN == D3DTEXF_POINT) {
2971                 /* GL_NEAREST_* */
2972               if (ValueMIP == D3DTEXF_NONE) {
2973                     realVal = GL_NEAREST;
2974                 } else if (ValueMIP == D3DTEXF_POINT) {
2975                     realVal = GL_NEAREST_MIPMAP_NEAREST;
2976                 } else if (ValueMIP == D3DTEXF_LINEAR) {
2977                     realVal = GL_NEAREST_MIPMAP_LINEAR;
2978                 } else {
2979                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2980                     realVal = GL_NEAREST;
2981                 }
2982             } else if (ValueMIN == D3DTEXF_LINEAR) {
2983                 /* GL_LINEAR_* */
2984                 if (ValueMIP == D3DTEXF_NONE) {
2985                     realVal = GL_LINEAR;
2986                 } else if (ValueMIP == D3DTEXF_POINT) {
2987                     realVal = GL_LINEAR_MIPMAP_NEAREST;
2988                 } else if (ValueMIP == D3DTEXF_LINEAR) {
2989                     realVal = GL_LINEAR_MIPMAP_LINEAR;
2990                 } else {
2991                     FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2992                     realVal = GL_LINEAR;
2993                 }
2994             } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
2995               if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2996                 if (ValueMIP == D3DTEXF_NONE) {
2997                   realVal = GL_LINEAR_MIPMAP_LINEAR;                  
2998                 } else if (ValueMIP == D3DTEXF_POINT) {
2999                   realVal = GL_LINEAR_MIPMAP_NEAREST;
3000                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3001                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3002                 } else {
3003                   FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3004                   realVal = GL_LINEAR;
3005                 }
3006               } else {
3007                 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3008                 realVal = GL_LINEAR;
3009               }
3010             } else {
3011                 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3012                 realVal = GL_LINEAR_MIPMAP_LINEAR;
3013             }
3014
3015             TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3016             glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3017             checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3018             /**
3019              * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3020              */
3021             if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3022               glTexParameteri(This->stateBlock->textureDimensions[Stage], 
3023                               GL_TEXTURE_MAX_ANISOTROPY_EXT, 
3024                               This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3025               checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3026             }
3027         }
3028         break;
3029
3030     case D3DTSS_MAGFILTER             :
3031       {
3032         DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
3033         GLint realVal = GL_NEAREST;
3034
3035         if (ValueMAG == D3DTEXF_POINT) {
3036           realVal = GL_NEAREST;
3037         } else if (ValueMAG == D3DTEXF_LINEAR) {
3038           realVal = GL_LINEAR;
3039         } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3040           if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3041             realVal = GL_LINEAR;
3042           } else {
3043             FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3044             realVal = GL_NEAREST;
3045           }
3046         } else {
3047           FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3048           realVal = GL_NEAREST;
3049         }
3050         TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3051         glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3052         checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3053         /**
3054          * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3055          */
3056         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3057           glTexParameteri(This->stateBlock->textureDimensions[Stage], 
3058                           GL_TEXTURE_MAX_ANISOTROPY_EXT, 
3059                           This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3060           checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3061         }
3062       }
3063       break;
3064
3065     case D3DTSS_MAXMIPLEVEL           :
3066       {
3067         /**
3068          * Not really the same, but the more apprioprate than nothing
3069          */
3070         glTexParameteri(This->stateBlock->textureDimensions[Stage], 
3071                         GL_TEXTURE_BASE_LEVEL, 
3072                         This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
3073         checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3074       }
3075       break;
3076
3077     case D3DTSS_MAXANISOTROPY         :
3078       {        
3079         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3080           glTexParameteri(This->stateBlock->textureDimensions[Stage], 
3081                           GL_TEXTURE_MAX_ANISOTROPY_EXT, 
3082                           This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
3083           checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3084         }
3085       }
3086       break;
3087
3088     case D3DTSS_MIPMAPLODBIAS         :
3089       {        
3090         if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3091           tmpvalue.d = Value;
3092           glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, 
3093                     GL_TEXTURE_LOD_BIAS_EXT,
3094                     tmpvalue.f);
3095           checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3096         }
3097       }
3098       break;
3099
3100     case D3DTSS_ALPHAOP               :
3101     case D3DTSS_COLOROP               :
3102         {
3103
3104             if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3105                 /* TODO: Disable by making this and all later levels disabled */
3106                 glDisable(GL_TEXTURE_1D);
3107                 checkGLcall("Disable GL_TEXTURE_1D");
3108                 glDisable(GL_TEXTURE_2D);
3109                 checkGLcall("Disable GL_TEXTURE_2D");
3110                 glDisable(GL_TEXTURE_3D);
3111                 checkGLcall("Disable GL_TEXTURE_3D");
3112                 break; /* Don't bother setting the texture operations */
3113             } else {
3114                 /* Enable only the appropriate texture dimension */
3115                 if (Type == D3DTSS_COLOROP) {
3116                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3117                         glEnable(GL_TEXTURE_1D);
3118                         checkGLcall("Enable GL_TEXTURE_1D");
3119                     } else {
3120                         glDisable(GL_TEXTURE_1D);
3121                         checkGLcall("Disable GL_TEXTURE_1D");
3122                     } 
3123                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3124                       if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3125                         glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3126                         checkGLcall("Enable GL_TEXTURE_2D");
3127                       } else {
3128                         glEnable(GL_TEXTURE_2D);
3129                         checkGLcall("Enable GL_TEXTURE_2D");
3130                       }
3131                     } else {
3132                         glDisable(GL_TEXTURE_2D);
3133                         checkGLcall("Disable GL_TEXTURE_2D");
3134                     }
3135                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3136                         glEnable(GL_TEXTURE_3D);
3137                         checkGLcall("Enable GL_TEXTURE_3D");
3138                     } else {
3139                         glDisable(GL_TEXTURE_3D);
3140                         checkGLcall("Disable GL_TEXTURE_3D");
3141                     }
3142                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3143                         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3144                         checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3145                     } else {
3146                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3147                         checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3148                     }
3149                 }
3150             }
3151             /* Drop through... (Except disable case) */
3152         case D3DTSS_COLORARG0             :
3153         case D3DTSS_COLORARG1             :
3154         case D3DTSS_COLORARG2             :
3155         case D3DTSS_ALPHAARG0             :
3156         case D3DTSS_ALPHAARG1             :
3157         case D3DTSS_ALPHAARG2             :
3158             {
3159                 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 || 
3160                                    Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3161                 if (isAlphaArg) {
3162                     set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
3163                                This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1], 
3164                                This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2], 
3165                                This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
3166                 } else {
3167                     set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
3168                                This->stateBlock->textureState[Stage][D3DTSS_COLORARG1], 
3169                                This->stateBlock->textureState[Stage][D3DTSS_COLORARG2], 
3170                                This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
3171                 }
3172             }
3173             break;
3174         }
3175
3176     case D3DTSS_ADDRESSU              :
3177     case D3DTSS_ADDRESSV              :
3178     case D3DTSS_ADDRESSW              :
3179         {
3180             GLint wrapParm = GL_REPEAT;
3181
3182             switch (Value) {
3183             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
3184             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;      
3185             case D3DTADDRESS_BORDER: 
3186               {
3187                 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3188                   wrapParm = GL_CLAMP_TO_BORDER_ARB; 
3189                 } else {
3190                   /* FIXME: Not right, but better */
3191                   FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3192                   wrapParm = GL_REPEAT; 
3193                 }
3194               }
3195               break;
3196             case D3DTADDRESS_MIRROR: 
3197               {
3198                 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3199                   wrapParm = GL_MIRRORED_REPEAT_ARB;
3200                 } else {
3201                   /* Unsupported in OpenGL pre-1.4 */
3202                   FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3203                   wrapParm = GL_REPEAT;
3204                 }
3205               }
3206               break;
3207             case D3DTADDRESS_MIRRORONCE: 
3208               {
3209                 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3210                   wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3211                 } else {
3212                   FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3213                   wrapParm = GL_REPEAT; 
3214                 }
3215               }
3216               break;
3217
3218             default:
3219                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3220                 wrapParm = GL_REPEAT; 
3221             }
3222
3223             switch (Type) {
3224             case D3DTSS_ADDRESSU:
3225                 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3226                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3227                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3228                 break;
3229             case D3DTSS_ADDRESSV:
3230                 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3231                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3232                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3233                 break;
3234             case D3DTSS_ADDRESSW:
3235                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3236                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3237                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3238                 break;
3239             default: /* nop */
3240                       break; /** stupic compilator */
3241             }
3242         }
3243         break;
3244
3245     case D3DTSS_BORDERCOLOR           :
3246         {
3247             float col[4];
3248             D3DCOLORTOGLFLOAT4(Value, col);
3249             TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value); 
3250             glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3251             checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3252         }
3253         break;
3254
3255     case D3DTSS_TEXCOORDINDEX         :
3256         {
3257             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3258
3259             /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include 
3260                   one flag, you can still specify an index value, which the system uses to 
3261                   determine the texture wrapping mode.  
3262                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3263                   means use the vertex position (camera-space) as the input texture coordinates 
3264                   for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3265                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3266                   to the TEXCOORDINDEX value */
3267           
3268             /** 
3269              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos 
3270              */
3271             switch (Value & 0xFFFF0000) {
3272             case D3DTSS_TCI_PASSTHRU:
3273               /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3274               glDisable(GL_TEXTURE_GEN_S);
3275               glDisable(GL_TEXTURE_GEN_T);
3276               glDisable(GL_TEXTURE_GEN_R);
3277               checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3278               break;
3279
3280             case D3DTSS_TCI_CAMERASPACEPOSITION:
3281               /* CameraSpacePosition means use the vertex position, transformed to camera space, 
3282                  as the input texture coordinates for this stage's texture transformation. This 
3283                  equates roughly to EYE_LINEAR                                                  */
3284               {
3285                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3286                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3287                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3288                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3289                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3290
3291                 glMatrixMode(GL_MODELVIEW);
3292                 glPushMatrix();
3293                 glLoadIdentity();
3294                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3295                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3296                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3297                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3298                 glPopMatrix();
3299                 
3300                 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3301                 glEnable(GL_TEXTURE_GEN_S);
3302                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3303                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3304                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3305                 glEnable(GL_TEXTURE_GEN_T);
3306                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3307                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3308                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3309                 glEnable(GL_TEXTURE_GEN_R);
3310                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3311                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3312                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3313               }
3314               break;
3315
3316             case D3DTSS_TCI_CAMERASPACENORMAL:
3317               {
3318                 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3319                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3320                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3321                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3322                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3323                   TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3324
3325                   glMatrixMode(GL_MODELVIEW);
3326                   glPushMatrix();
3327                   glLoadIdentity();
3328                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3329                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3330                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3331                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3332                   glPopMatrix();
3333                   
3334                   glEnable(GL_TEXTURE_GEN_S);
3335                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3336                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3337                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3338                   glEnable(GL_TEXTURE_GEN_T);
3339                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3340                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3341                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3342                   glEnable(GL_TEXTURE_GEN_R);
3343                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3344                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3345                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3346                 }
3347               }
3348               break;
3349
3350             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3351               {
3352                 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3353                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3354                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3355                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3356                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3357                   TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3358                   
3359                   glMatrixMode(GL_MODELVIEW);
3360                   glPushMatrix();
3361                   glLoadIdentity();
3362                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3363                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3364                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3365                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3366                   glPopMatrix();
3367                   
3368                   glEnable(GL_TEXTURE_GEN_S);
3369                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3370                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3371                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3372                   glEnable(GL_TEXTURE_GEN_T);
3373                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3374                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3375                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3376                   glEnable(GL_TEXTURE_GEN_R);
3377                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3378                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3379                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3380                 }
3381               }
3382               break;
3383
3384             /* Unhandled types: */
3385             default:
3386                 /* Todo: */
3387                 /* ? disable GL_TEXTURE_GEN_n ? */ 
3388                 glDisable(GL_TEXTURE_GEN_S);
3389                 glDisable(GL_TEXTURE_GEN_T);
3390                 glDisable(GL_TEXTURE_GEN_R);
3391                 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3392                 break;
3393             }
3394         }
3395         break;
3396
3397         /* Unhandled */
3398     case D3DTSS_TEXTURETRANSFORMFLAGS :
3399         set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3400         break; 
3401
3402     case D3DTSS_BUMPENVMAT00          :
3403     case D3DTSS_BUMPENVMAT01          :
3404         TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3405         break;
3406     case D3DTSS_BUMPENVMAT10          :
3407     case D3DTSS_BUMPENVMAT11          :
3408         TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3409         break;
3410
3411     case D3DTSS_BUMPENVLSCALE         :
3412       TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3413       break;
3414
3415     case D3DTSS_BUMPENVLOFFSET        :
3416       TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3417       break;
3418
3419     case D3DTSS_RESULTARG             :
3420       TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3421       break;
3422
3423     default:
3424         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3425         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3426     }
3427
3428     LEAVE_GL();
3429
3430     return D3D_OK;
3431 }
3432
3433 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3434     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3435     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3436     *pValue = This->updateStateBlock->textureState[Stage][Type];
3437     return D3D_OK;
3438 }
3439
3440 /*****
3441  * Get / Set Texture 
3442  *****/
3443 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3444
3445     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3446     IWineD3DBaseTexture   *oldTexture;
3447     BOOL                   reapplyStates = TRUE;
3448     DWORD                  reapplyFlags = 0;
3449     INT                    oldTextureDimensions = -1;
3450     D3DRESOURCETYPE        textureType;
3451
3452     oldTexture = This->updateStateBlock->textures[Stage];
3453     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3454
3455     /* Reject invalid texture units */
3456     if (Stage >= GL_LIMITS(textures)) {
3457         TRACE("Attempt to access invalid texture rejected\n");
3458         return D3DERR_INVALIDCALL;
3459     }
3460
3461     This->updateStateBlock->set.textures[Stage] = TRUE;
3462     This->updateStateBlock->changed.textures[Stage] = TRUE;
3463     This->updateStateBlock->textures[Stage] = pTexture;
3464
3465     /* Handle recording of state blocks */
3466     if (This->isRecordingState) {
3467         TRACE("Recording... not performing anything\n");
3468         return D3D_OK;
3469     }
3470
3471     oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
3472
3473     ENTER_GL();
3474
3475     /* Make appropriate texture active */
3476     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3477         GLACTIVETEXTURE(Stage);
3478
3479     } else if (Stage>0) {
3480         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3481     }
3482
3483     /** NOTE: MSDN says that setTexture increases the reference count,
3484     * and the the application nust set the texture back to null (or have a leaky application),
3485     * This means we should pass the refcount upto the parent
3486      *******************************/
3487     if (NULL != oldTexture) {
3488
3489         IUnknown *textureParent;
3490         IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
3491         IUnknown_Release(textureParent);
3492         IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
3493         oldTexture = NULL;
3494     }
3495     
3496
3497     if (NULL != pTexture) {
3498         IUnknown *textureParent;
3499         IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
3500         /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
3501
3502         /* Now setup the texture appropraitly */
3503         textureType = IWineD3DBaseTexture_GetType(pTexture);
3504
3505         if (textureType == D3DRTYPE_TEXTURE) {
3506
3507           if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3508             TRACE("Skipping setting texture as old == new\n");
3509             reapplyStates = FALSE;
3510
3511           } else {
3512
3513             /* Standard 2D texture */
3514             TRACE("Standard 2d texture\n");
3515             This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3516
3517             /* Load up the texture now */
3518             IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
3519           }
3520
3521         } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3522
3523           if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3524               TRACE("Skipping setting texture as old == new\n");
3525               reapplyStates = FALSE;
3526
3527           } else {
3528
3529               /* Standard 3D (volume) texture */
3530               TRACE("Standard 3d texture\n");
3531               This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3532
3533               /* Load up the texture now */
3534               IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
3535           }
3536
3537         } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3538
3539             if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3540                 TRACE("Skipping setting texture as old == new\n");
3541                 reapplyStates = FALSE;
3542
3543             } else {
3544
3545                 /* Standard Cube texture */
3546                 TRACE("Standard Cube texture\n");
3547                 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3548
3549                 /* Load up the texture now */
3550                 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
3551             }
3552
3553         } else {
3554             FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
3555         }
3556
3557     } else {
3558
3559         TRACE("Setting to no texture (ie default texture)\n");
3560         This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3561         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3562         checkGLcall("glBindTexture");
3563         TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3564     }
3565
3566     /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3567     if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
3568
3569        glDisable(oldTextureDimensions);
3570        checkGLcall("Disable oldTextureDimensions");
3571
3572        if (This->stateBlock->textureState[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3573           glEnable(This->updateStateBlock->textureDimensions[Stage]);
3574           checkGLcall("glEnable new texture dimensions");
3575        }
3576
3577        /* If Alpha arg1 is texture then handle the special case when there changes between a
3578           texture and no texture - See comments in set_tex_op                                  */
3579        if ((This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) && 
3580            (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
3581        {
3582            reapplyFlags |= REAPPLY_ALPHAOP;
3583        }
3584     }
3585
3586
3587     /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3588        a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3589     if (reapplyStates) {
3590        IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
3591     }
3592
3593     LEAVE_GL();   
3594     TRACE("Texture now fully setup\n");
3595
3596     return D3D_OK;
3597 }
3598
3599 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3600     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3601     TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
3602     *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
3603     if (*ppTexture)
3604         IWineD3DBaseTexture_AddRef(*ppTexture);
3605     return D3D_OK;
3606 }
3607
3608 /*****
3609  * Get Back Buffer
3610  *****/
3611 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, 
3612                                                 IWineD3DSurface** ppBackBuffer) {
3613     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3614     
3615     *ppBackBuffer = (IWineD3DSurface *) This->backBuffer;
3616     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3617
3618     if (BackBuffer > This->presentParms.BackBufferCount - 1) {
3619         FIXME("Only one backBuffer currently supported\n");
3620         return D3DERR_INVALIDCALL;
3621     }
3622
3623     /* Note inc ref on returned surface */
3624     IWineD3DSurface_AddRef(*ppBackBuffer);
3625
3626     return D3D_OK;
3627 }
3628
3629 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, D3DCAPS9* pCaps) {
3630     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3631     WARN("(%p) : stub, calling idirect3d for now\n", This);
3632     IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3633     return D3D_OK;
3634 }
3635
3636 /** TODO: move to swapchains **/
3637 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
3638     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3639     HDC                 hdc;
3640     int                 bpp = 0;
3641
3642     pMode->Width        = GetSystemMetrics(SM_CXSCREEN);
3643     pMode->Height       = GetSystemMetrics(SM_CYSCREEN);
3644     pMode->RefreshRate  = 85; /*FIXME: How to identify? */
3645
3646     hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
3647     bpp = GetDeviceCaps(hdc, BITSPIXEL);
3648     DeleteDC(hdc);
3649
3650     switch (bpp) {
3651     case  8: pMode->Format       = WINED3DFMT_R8G8B8; break;
3652     case 16: pMode->Format       = WINED3DFMT_R5G6B5; break;
3653     case 24: /*pMode->Format       = WINED3DFMT_R8G8B8; break; */
3654     case 32: pMode->Format       = WINED3DFMT_A8R8G8B8; break;
3655     default: 
3656        FIXME("Unrecognized display mode format\n");
3657        pMode->Format       = WINED3DFMT_UNKNOWN;
3658     }
3659
3660     FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, 
3661           pMode->Format, debug_d3dformat(pMode->Format));
3662     return D3D_OK;
3663 }
3664 /*****
3665  * Stateblock related functions
3666  *****/
3667
3668  HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
3669     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3670     IWineD3DStateBlockImpl *object;
3671     TRACE("(%p)", This);
3672     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
3673     if(NULL == object ){
3674         FIXME("(%p)Error allocating memory for stateblock\n", This);
3675         return E_OUTOFMEMORY;
3676     }
3677     TRACE("(%p) creted object %p\n", This, object);
3678     object->wineD3DDevice= This;    
3679     /** FIXME: object->parent       = parent; **/
3680     object->parent       = NULL;
3681     object->blockType    = D3DSBT_ALL;    
3682     object->ref          = 1;
3683     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;   
3684     
3685     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
3686     This->updateStateBlock = object;
3687     This->isRecordingState = TRUE;
3688     
3689     TRACE("(%p) recording stateblock %p\n",This , object);
3690     return D3D_OK; 
3691 }
3692
3693 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
3694     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3695
3696     if (!This->isRecordingState) {
3697         FIXME("(%p) not recording! returning error\n", This);
3698         *ppStateBlock = NULL;
3699         return D3DERR_INVALIDCALL;
3700     }
3701
3702     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
3703     This->isRecordingState = FALSE;
3704     This->updateStateBlock = This->stateBlock;    
3705     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
3706     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
3707     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
3708     return D3D_OK;  
3709 }
3710
3711 /*****
3712  * Scene related functions
3713  *****/
3714 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
3715     /* At the moment we have no need for any functionality at the beginning
3716        of a scene                                                          */
3717     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3718     TRACE("(%p) : stub\n", This);
3719     return D3D_OK;
3720 }
3721
3722 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
3723     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3724     TRACE("(%p)\n", This);
3725     ENTER_GL();
3726     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
3727     glFlush();
3728     checkGLcall("glFlush");
3729
3730     TRACE("End Scene\n");
3731     if(This->renderTarget != NULL){
3732
3733         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
3734         IUnknown *targetContainer = NULL;
3735         if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
3736             TRACE("RenderTarget is either standalone of a texture.\n");
3737             /** always dirtify for now. we must find a better way to see that surface have been modified
3738             (Modifications should will only occur via draw-primitive, but we do need better locking
3739             switching to render-to-texture should remove the overhead though.
3740             */
3741             IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
3742             IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
3743             IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
3744             IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
3745             IUnknown_Release(targetContainer);
3746         }
3747
3748     }
3749
3750     LEAVE_GL();
3751     return D3D_OK;
3752 }
3753
3754 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface, 
3755                                           CONST RECT* pSourceRect, CONST RECT* pDestRect, 
3756                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
3757     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3758     TRACE("(%p) Presenting the frame\n", This);
3759
3760     ENTER_GL();
3761
3762     if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
3763
3764     glXSwapBuffers(This->display, This->drawable);
3765     /* Don't call checkGLcall, as glGetError is not applicable here */
3766     
3767     TRACE("glXSwapBuffers called, Starting new frame\n");
3768
3769     /* FPS support */
3770     if (TRACE_ON(d3d_fps))
3771     {
3772         static long prev_time, frames;
3773
3774         DWORD time = GetTickCount();
3775         frames++;
3776         /* every 1.5 seconds */
3777         if (time - prev_time > 1500) {
3778             TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
3779             prev_time = time;
3780             frames = 0;
3781         }
3782     }
3783
3784 #if defined(FRAME_DEBUGGING)
3785 {
3786     if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
3787         if (!isOn) {
3788             isOn = TRUE;
3789             FIXME("Enabling D3D Trace\n");
3790             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
3791 #if defined(SHOW_FRAME_MAKEUP)
3792             FIXME("Singe Frame snapshots Starting\n");
3793             isDumpingFrames = TRUE;
3794             glClear(GL_COLOR_BUFFER_BIT);
3795 #endif
3796
3797 #if defined(SINGLE_FRAME_DEBUGGING)
3798         } else {
3799 #if defined(SHOW_FRAME_MAKEUP)
3800             FIXME("Singe Frame snapshots Finishing\n");
3801             isDumpingFrames = FALSE;
3802 #endif
3803             FIXME("Singe Frame trace complete\n");
3804             DeleteFileA("C:\\D3DTRACE");
3805             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3806 #endif
3807         }
3808     } else {
3809         if (isOn) {
3810             isOn = FALSE;
3811 #if defined(SHOW_FRAME_MAKEUP)
3812             FIXME("Singe Frame snapshots Finishing\n");
3813             isDumpingFrames = FALSE;
3814 #endif
3815             FIXME("Disabling D3D Trace\n");
3816             __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3817         }
3818     }
3819 }
3820 #endif
3821
3822     LEAVE_GL();
3823     /* Although this is not strictly required, a simple demo showed this does occur
3824        on (at least non-debug) d3d                                                  */
3825     if (This->presentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
3826        IWineD3DDevice_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
3827     }
3828
3829     return D3D_OK;
3830 }
3831
3832 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects, 
3833                                         DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
3834     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3835
3836     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
3837       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
3838       when the depth-buffer format does not contain stencil buffer information, this method fails. */
3839     GLbitfield     glMask = 0;
3840     GLboolean      old_ztest;
3841     GLfloat        old_z_clear_value;
3842     GLint          old_stencil_clear_value;
3843     GLfloat        old_color_clear_value[4];
3844     unsigned int   i;
3845     CONST D3DRECT* curRect;
3846
3847     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
3848           Count, pRects, Flags, Z, Stencil);
3849
3850     ENTER_GL();
3851
3852     glEnable(GL_SCISSOR_TEST);
3853     checkGLcall("glEnable GL_SCISSOR_TEST");
3854
3855     if (Count > 0 && pRects) {
3856         curRect = pRects;
3857     } else {
3858         curRect = NULL;
3859     }
3860
3861     /* Only set the values up once, as they are not changing */
3862     if (Flags & D3DCLEAR_STENCIL) {        
3863         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
3864         glClearStencil(Stencil);
3865         checkGLcall("glClearStencil");
3866         glMask = glMask | GL_STENCIL_BUFFER_BIT;
3867         glStencilMask(0xFFFFFFFF);
3868     }
3869
3870     if (Flags & D3DCLEAR_ZBUFFER) {
3871         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
3872         glDepthMask(GL_TRUE); 
3873         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
3874         glClearDepth(Z);
3875         checkGLcall("glClearDepth");
3876         glMask = glMask | GL_DEPTH_BUFFER_BIT;
3877     }
3878
3879     if (Flags & D3DCLEAR_TARGET) {
3880         TRACE("Clearing screen with glClear to color %lx\n", Color);
3881         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
3882         glClearColor(((Color >> 16) & 0xFF) / 255.0f, 
3883                      ((Color >>  8) & 0xFF) / 255.0f,
3884                      ((Color >>  0) & 0xFF) / 255.0f, 
3885                      ((Color >> 24) & 0xFF) / 255.0f);
3886         checkGLcall("glClearColor");
3887
3888         /* Clear ALL colors! */
3889         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3890         glMask = glMask | GL_COLOR_BUFFER_BIT;
3891     }
3892
3893     /* Now process each rect in turn */
3894     for (i = 0; i < Count || i == 0; i++) {
3895
3896         if (curRect) {
3897             /* Note gl uses lower left, width/height */
3898             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
3899                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
3900                   curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2), 
3901                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3902             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2), 
3903                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3904             checkGLcall("glScissor");
3905         } else {
3906             glScissor(This->stateBlock->viewport.X, 
3907                       (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)), 
3908                       This->stateBlock->viewport.Width, 
3909                       This->stateBlock->viewport.Height);
3910             checkGLcall("glScissor");
3911         }
3912
3913         /* Clear the selected rectangle (or full screen) */
3914         glClear(glMask);
3915         checkGLcall("glClear");
3916
3917         /* Step to the next rectangle */
3918         if (curRect) curRect = curRect + sizeof(D3DRECT);
3919     }
3920
3921     /* Restore the old values (why..?) */
3922     if (Flags & D3DCLEAR_STENCIL) {
3923         glClearStencil(old_stencil_clear_value);
3924         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
3925     }    
3926     if (Flags & D3DCLEAR_ZBUFFER) {
3927         glDepthMask(old_ztest);
3928         glClearDepth(old_z_clear_value);
3929     }
3930     if (Flags & D3DCLEAR_TARGET) {
3931         glClearColor(old_color_clear_value[0], 
3932                      old_color_clear_value[1],
3933                      old_color_clear_value[2], 
3934                      old_color_clear_value[3]);
3935         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3936                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3937                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
3938                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3939     }
3940
3941     glDisable(GL_SCISSOR_TEST);
3942     checkGLcall("glDisable");
3943     LEAVE_GL();
3944
3945     return D3D_OK;
3946 }
3947
3948 /*****
3949  * Drawing functions
3950  *****/
3951 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, 
3952                                                 UINT PrimitiveCount) {
3953
3954     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3955     This->stateBlock->streamIsUP = FALSE;
3956
3957     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, 
3958                                debug_d3dprimitivetype(PrimitiveType), 
3959                                StartVertex, PrimitiveCount);
3960     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3961
3962     return D3D_OK;
3963 }
3964
3965 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
3966 HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface, 
3967                                                            D3DPRIMITIVETYPE PrimitiveType,
3968                                                            INT baseVIndex, UINT minIndex,
3969                                                            UINT NumVertices,UINT startIndex,UINT primCount) {
3970
3971     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
3972     UINT                 idxStride = 2;
3973     IWineD3DIndexBuffer *pIB;
3974     D3DINDEXBUFFER_DESC  IdxBufDsc;
3975     
3976     pIB = This->stateBlock->pIndexData;
3977     This->stateBlock->streamIsUP = FALSE;
3978
3979     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This, 
3980           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3981           minIndex, NumVertices, startIndex, baseVIndex, primCount);
3982
3983     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
3984     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
3985         idxStride = 2;
3986     } else {
3987         idxStride = 4;
3988     }
3989
3990     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, 
3991                       startIndex, idxStride, 
3992                       ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
3993                       minIndex);
3994
3995     return D3D_OK;
3996 }
3997
3998 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3999                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4000                                                     UINT VertexStreamZeroStride) {
4001     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4002
4003     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, 
4004              debug_d3dprimitivetype(PrimitiveType), 
4005              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4006
4007     if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4008
4009     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4010     This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData; 
4011     This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4012     This->stateBlock->streamIsUP = TRUE;
4013     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4014     This->stateBlock->stream_stride[0] = 0;
4015     This->stateBlock->stream_source[0] = NULL;
4016
4017     /*stream zero settings set to null at end, as per the msdn */
4018     return D3D_OK;
4019 }
4020
4021 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4022                                                              UINT MinVertexIndex,
4023                                                              UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4024                                                              WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4025                                                              UINT VertexStreamZeroStride) {
4026     int                 idxStride;
4027     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4028
4029     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", 
4030              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4031              MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,  
4032              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4033
4034     if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
4035
4036     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4037         idxStride = 2;
4038     } else {
4039         idxStride = 4;
4040     }
4041
4042     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4043     This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4044     This->stateBlock->streamIsUP = TRUE;
4045     This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
4046
4047     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4048
4049     /* stream zero settings set to null at end as per the msdn */
4050     This->stateBlock->stream_source[0] = NULL;
4051     This->stateBlock->stream_stride[0] = 0;
4052     IWineD3DDevice_SetIndices(iface, NULL, 0);
4053
4054     return D3D_OK;
4055 }
4056
4057 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4058     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4059     
4060     TRACE("(%p) : stub\n", This);
4061     return D3D_OK;
4062 }
4063
4064 HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4065                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4066                                                 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4067     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4068     
4069     TRACE("(%p) : stub\n", This);
4070     return D3D_OK;
4071 }
4072 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4073     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4074     
4075     TRACE("(%p) : stub\n", This);
4076     return D3D_OK;
4077 }
4078
4079 HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4080     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4081     
4082     TRACE("(%p) : stub\n", This);
4083     return D3D_OK;
4084 }
4085
4086 HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4087     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4088     /* return a sensible default */
4089     *pNumPasses = 1;
4090     FIXME("(%p) : stub\n", This);
4091     return D3D_OK;
4092 }
4093
4094 HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4095     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;  
4096     FIXME("(%p) : stub\n", This);
4097     return D3D_OK;
4098 }
4099
4100 HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4101     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4102     FIXME("(%p) : stub\n", This);
4103     return D3D_OK;
4104 }
4105
4106 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4107     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4108     FIXME("(%p) : stub\n", This);
4109     return D3D_OK;
4110 }
4111
4112 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4113     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4114     FIXME("(%p) : stub\n", This);
4115     return D3D_OK;
4116 }
4117
4118 HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4119     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4120     FIXME("(%p) : stub\n", This);
4121     return D3D_OK;
4122 }
4123
4124
4125 BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4126     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4127     FIXME("(%p) : stub\n", This);
4128     return FALSE;
4129 }
4130
4131
4132 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4133     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4134         
4135     pRasterStatus->InVBlank = TRUE;
4136     pRasterStatus->ScanLine = 0;
4137     FIXME("(%p) : stub\n", This);
4138     return D3D_OK;
4139 }
4140
4141
4142 HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4143     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4144     static BOOL showfixmes = TRUE;
4145     if(nSegments != 0.0f){
4146         if( showfixmes){
4147             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4148             showfixmes = FALSE;
4149         }
4150     }
4151     return D3D_OK;
4152 }
4153
4154 float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4155     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4156     static BOOL showfixmes = TRUE;
4157     if( showfixmes){
4158         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4159         showfixmes = FALSE;
4160     }
4161     return 0.0f;
4162 }
4163
4164
4165 HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4166     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4167     FIXME("(%p) : stub\n", This);
4168     return D3D_OK;
4169
4170 }
4171
4172 /* Implementation details at http://developer.nvidia.com/attach/6494
4173 and
4174 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4175 hmm.. no longer supported use
4176 OpenGL evaluators or  tessellate surfaces within your application.
4177 */
4178
4179 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4180 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4181     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4182     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4183     FIXME("(%p) : Stub\n", This);
4184     return D3D_OK;
4185
4186 }
4187
4188 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4189 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4190     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4191     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4192     FIXME("(%p) : Stub\n", This);
4193     return D3D_OK;
4194 }
4195
4196 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){    
4197     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4198     TRACE("(%p) Handle(%d)\n", This, Handle);
4199     FIXME("(%p) : Stub\n", This);
4200     return D3D_OK;
4201
4202
4203 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4204     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4205
4206     FIXME("(%p) : stub\n", This);
4207     return D3D_OK;
4208 }
4209
4210 /* rendertarget and deptth stencil functions */
4211 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4212     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4213     
4214     /* FIXME: Implelent RenderTargetIndex >0 */
4215     if(RenderTargetIndex > 0)
4216         FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4217     
4218     *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4219     TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4220     /* Note inc ref on returned surface */
4221     if(*ppRenderTarget != NULL)
4222         IWineD3DSurface_AddRef(*ppRenderTarget);
4223     return D3D_OK;
4224 }
4225
4226 HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4227     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4228     *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4229     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
4230
4231     if(*ppZStencilSurface != NULL){
4232         /* Note inc ref on returned surface */
4233         IWineD3DSurface_AddRef(*ppZStencilSurface);
4234     }
4235     return D3D_OK;
4236 }
4237
4238 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4239     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4240
4241     FIXME("(%p) : stub\n", This);
4242     return D3D_OK;
4243 }
4244
4245 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4246     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4247
4248     FIXME("(%p) : stub\n", This);
4249     return D3D_OK;
4250 }
4251
4252 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
4253                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
4254     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;    
4255     /* TODO: the use of Impl is deprecated. */
4256     /* some basic validation checks */    
4257     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
4258
4259     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
4260
4261     if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
4262       ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
4263       return D3DERR_INVALIDCALL;
4264     }
4265     if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
4266       ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
4267       return D3DERR_INVALIDCALL;
4268     }
4269     /* TODO: make the cursor 'real' */
4270     
4271     This->xHotSpot = XHotSpot;
4272     This->yHotSpot = YHotSpot;
4273     
4274     return D3D_OK;    
4275 }
4276
4277 void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
4278     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4279     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
4280     
4281     This->xScreenSpace = XScreenSpace;
4282     This->yScreenSpace = YScreenSpace;
4283     
4284     return;
4285
4286 }
4287
4288 BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
4289     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;    
4290     TRACE("(%p) : visible(%d)\n", This, bShow);
4291     
4292     This->bCursorVisible = bShow;
4293     
4294     return D3D_OK;    
4295 }
4296
4297 HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
4298     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4299     FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
4300     return D3D_OK;
4301 }
4302
4303
4304 HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
4305     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4306     /** FIXME: Resource tracking needs to be done,
4307     * The closes we can do to this is set the priorities of all managed textures low
4308     * and then reset them.
4309      ***********************************************************/
4310     FIXME("(%p) : stub\n", This);
4311     return D3D_OK;
4312 }
4313
4314 HRESULT  WINAPI  IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
4315     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4316     /** FIXME: Resource trascking needs to be done.
4317     * in effect this pulls all non only default
4318     * textures out of video memory and deletes all glTextures (glDeleteTextures)
4319     * and should clear down the context and set it up according to pPresentationParameters
4320      ***********************************************************/
4321     FIXME("(%p) : stub\n", This);    
4322     return D3D_OK;
4323 }
4324
4325 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
4326     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4327     /** FIXME: always true at the moment **/
4328     if(bEnableDialogs == FALSE){
4329         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
4330     }
4331     return D3D_OK; 
4332 }
4333
4334
4335 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
4336     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4337     
4338     FIXME("(%p) : stub\n", This);
4339     /* Setup some reasonable defaults */
4340     pParameters->AdapterOrdinal = 0; /* always for now */
4341     pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
4342     pParameters->hFocusWindow = 0;
4343     pParameters->BehaviorFlags =0;    
4344     return D3D_OK;
4345 }
4346
4347 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
4348     HDC hDC;
4349     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4350     
4351     FIXME("(%p) : pRamp@%p\n", This, pRamp);
4352     hDC = GetDC(This->win_handle);
4353     SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
4354     ReleaseDC(This->win_handle, hDC);
4355     return;
4356 }
4357
4358 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
4359     HDC hDC;
4360     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4361
4362     FIXME("(%p) : pRamp@%p\n", This, pRamp);
4363     hDC = GetDC(This->win_handle);
4364     GetDeviceGammaRamp(hDC, pRamp);
4365     ReleaseDC(This->win_handle, hDC);
4366     return;
4367 }
4368
4369 /**********************************************************
4370  * IWineD3DDevice VTbl follows
4371  **********************************************************/
4372
4373 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
4374 {
4375     /*** IUnknown methods ***/
4376     IWineD3DDeviceImpl_QueryInterface,
4377     IWineD3DDeviceImpl_AddRef,
4378     IWineD3DDeviceImpl_Release,
4379     /*** IWineD3DDevice methods ***/
4380     IWineD3DDeviceImpl_GetParent,
4381     /*** Creation methods**/
4382     IWineD3DDeviceImpl_CreateVertexBuffer,
4383     IWineD3DDeviceImpl_CreateIndexBuffer,
4384     IWineD3DDeviceImpl_CreateStateBlock,
4385     IWineD3DDeviceImpl_CreateSurface,
4386     IWineD3DDeviceImpl_CreateTexture,
4387     IWineD3DDeviceImpl_CreateVolumeTexture,
4388     IWineD3DDeviceImpl_CreateVolume,
4389     IWineD3DDeviceImpl_CreateCubeTexture,
4390     IWineD3DDeviceImpl_CreateQuery,
4391     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
4392     IWineD3DDeviceImpl_CreateVertexDeclaration,
4393     IWineD3DDeviceImpl_CreateVertexShader,
4394     IWineD3DDeviceImpl_CreatePixelShader,
4395     
4396     /*** Odd functions **/
4397     IWineD3DDeviceImpl_EvictManagedResources,        
4398     IWineD3DDeviceImpl_GetAvailableTextureMem,
4399     IWineD3DDeviceImpl_GetBackBuffer,
4400     IWineD3DDeviceImpl_GetCreationParameters,
4401     IWineD3DDeviceImpl_GetDeviceCaps,
4402     IWineD3DDeviceImpl_GetDirect3D,
4403     IWineD3DDeviceImpl_GetDisplayMode,
4404     IWineD3DDeviceImpl_GetNumberOfSwapChains,
4405     IWineD3DDeviceImpl_GetRasterStatus,
4406     IWineD3DDeviceImpl_GetSwapChain,
4407     IWineD3DDeviceImpl_Reset,
4408     IWineD3DDeviceImpl_SetDialogBoxMode,
4409     IWineD3DDeviceImpl_SetCursorProperties,
4410     IWineD3DDeviceImpl_SetCursorPosition,
4411     IWineD3DDeviceImpl_ShowCursor,
4412     IWineD3DDeviceImpl_TestCooperativeLevel,
4413     /*** Getters and setters **/
4414     IWineD3DDeviceImpl_SetClipPlane,
4415     IWineD3DDeviceImpl_GetClipPlane,
4416     IWineD3DDeviceImpl_SetClipStatus,
4417     IWineD3DDeviceImpl_GetClipStatus,
4418     IWineD3DDeviceImpl_SetCurrentTexturePalette,
4419     IWineD3DDeviceImpl_GetCurrentTexturePalette,
4420     IWineD3DDeviceImpl_SetDepthStencilSurface,
4421     IWineD3DDeviceImpl_GetDepthStencilSurface,
4422     IWineD3DDeviceImpl_SetFVF,
4423     IWineD3DDeviceImpl_GetFVF,
4424     IWineD3DDeviceImpl_SetGammaRamp,
4425     IWineD3DDeviceImpl_GetGammaRamp,    
4426     IWineD3DDeviceImpl_SetIndices,
4427     IWineD3DDeviceImpl_GetIndices,    
4428     IWineD3DDeviceImpl_SetLight,
4429     IWineD3DDeviceImpl_GetLight,
4430     IWineD3DDeviceImpl_SetLightEnable,
4431     IWineD3DDeviceImpl_GetLightEnable,
4432     IWineD3DDeviceImpl_SetMaterial,
4433     IWineD3DDeviceImpl_GetMaterial,
4434     IWineD3DDeviceImpl_SetNPatchMode,
4435     IWineD3DDeviceImpl_GetNPatchMode,    
4436     IWineD3DDeviceImpl_SetPaletteEntries,
4437     IWineD3DDeviceImpl_GetPaletteEntries,
4438     IWineD3DDeviceImpl_SetPixelShader,
4439     IWineD3DDeviceImpl_GetPixelShader,
4440     IWineD3DDeviceImpl_SetPixelShaderConstantB,
4441     IWineD3DDeviceImpl_GetPixelShaderConstantB,
4442     IWineD3DDeviceImpl_SetPixelShaderConstantI,
4443     IWineD3DDeviceImpl_GetPixelShaderConstantI,
4444     IWineD3DDeviceImpl_SetPixelShaderConstantF,
4445     IWineD3DDeviceImpl_GetPixelShaderConstantF,
4446     IWineD3DDeviceImpl_SetRenderState,
4447     IWineD3DDeviceImpl_GetRenderState,
4448     IWineD3DDeviceImpl_SetRenderTarget,
4449     IWineD3DDeviceImpl_GetRenderTarget,
4450     IWineD3DDeviceImpl_SetSamplerState,
4451     IWineD3DDeviceImpl_GetSamplerState,
4452     IWineD3DDeviceImpl_SetScissorRect,
4453     IWineD3DDeviceImpl_GetScissorRect,
4454     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
4455     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
4456     IWineD3DDeviceImpl_SetStreamSource,
4457     IWineD3DDeviceImpl_GetStreamSource,
4458     IWineD3DDeviceImpl_SetStreamSourceFreq,
4459     IWineD3DDeviceImpl_GetStreamSourceFreq,
4460     IWineD3DDeviceImpl_SetTexture,
4461     IWineD3DDeviceImpl_GetTexture,    
4462     IWineD3DDeviceImpl_SetTextureStageState,
4463     IWineD3DDeviceImpl_GetTextureStageState,
4464     IWineD3DDeviceImpl_SetTransform,
4465     IWineD3DDeviceImpl_GetTransform,
4466     IWineD3DDeviceImpl_SetVertexDeclaration,
4467     IWineD3DDeviceImpl_GetVertexDeclaration,
4468     IWineD3DDeviceImpl_SetVertexShader,
4469     IWineD3DDeviceImpl_GetVertexShader,
4470     IWineD3DDeviceImpl_SetVertexShaderConstantB,
4471     IWineD3DDeviceImpl_GetVertexShaderConstantB,
4472     IWineD3DDeviceImpl_SetVertexShaderConstantI,
4473     IWineD3DDeviceImpl_GetVertexShaderConstantI,
4474     IWineD3DDeviceImpl_SetVertexShaderConstantF,
4475     IWineD3DDeviceImpl_GetVertexShaderConstantF,
4476     IWineD3DDeviceImpl_SetViewport,
4477     IWineD3DDeviceImpl_GetViewport,
4478     IWineD3DDeviceImpl_MultiplyTransform,
4479     IWineD3DDeviceImpl_ValidateDevice,
4480     IWineD3DDeviceImpl_ProcessVertices,
4481     /*** State block ***/
4482     IWineD3DDeviceImpl_BeginStateBlock,
4483     IWineD3DDeviceImpl_EndStateBlock,
4484     /*** Scene management ***/
4485     IWineD3DDeviceImpl_BeginScene,
4486     IWineD3DDeviceImpl_EndScene,
4487     IWineD3DDeviceImpl_Present,
4488     IWineD3DDeviceImpl_Clear,
4489     /*** Drawing ***/
4490     IWineD3DDeviceImpl_DrawPrimitive,
4491     IWineD3DDeviceImpl_DrawIndexedPrimitive,
4492     IWineD3DDeviceImpl_DrawPrimitiveUP,
4493     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
4494     IWineD3DDeviceImpl_DrawRectPatch,
4495     IWineD3DDeviceImpl_DrawTriPatch,
4496     IWineD3DDeviceImpl_DeletePatch,
4497     IWineD3DDeviceImpl_ColorFill,
4498     IWineD3DDeviceImpl_UpdateTexture,
4499     IWineD3DDeviceImpl_UpdateSurface,
4500     IWineD3DDeviceImpl_StretchRect,
4501     IWineD3DDeviceImpl_GetRenderTargetData,
4502     IWineD3DDeviceImpl_GetFrontBufferData,
4503     /*** Internal use IWineD3DDevice methods ***/
4504     IWineD3DDeviceImpl_SetupTextureStates
4505 };