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