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