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