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