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