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