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