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