Fix some gcc 4.0 warnings.
[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     FIXME("(%p) : Stub\n", This);
1469     return D3D_OK;
1470 }
1471
1472 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1473    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1474    *ppD3D= This->wineD3D;
1475    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
1476    IWineD3D_AddRef(*ppD3D);
1477    return D3D_OK;
1478 }
1479
1480 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1481     /** NOTE: There's a probably  a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1482     * Into the video ram as possible and seeing how many fit
1483     * you can also get the correct initial value from via X and ATI's driver
1484     *******************/
1485     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1486     static BOOL showfixmes = TRUE;
1487     if (showfixmes) {
1488         FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1489          ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1490          showfixmes = FALSE;
1491     }
1492     TRACE("(%p) :  emulating %dMib for now, returning %dMib\n",  This, (emulated_textureram/(1024*1024)),
1493          ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1494     /* videomemory is simulated videomemory + AGP memory left */
1495     return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1496 }
1497
1498
1499
1500 /*****
1501  * Get / Set FVF
1502  *****/
1503 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1504     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1505
1506     /* Update the current state block */
1507     This->updateStateBlock->fvf              = fvf;
1508     This->updateStateBlock->changed.fvf      = TRUE;
1509     This->updateStateBlock->set.fvf          = TRUE;
1510
1511     TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1512     /* clear down the vertex declaration
1513      NOTE: Axis and Allies doesn't work properly otherwise
1514      (may be a stateblock problem though!)
1515     */
1516     /* No difference if recording or not */
1517     return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1518
1519 }
1520
1521
1522 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1523     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1524     TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1525     *pfvf = This->stateBlock->fvf;
1526     return D3D_OK;
1527 }
1528
1529 /*****
1530  * Get / Set Stream Source
1531  *****/
1532 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1533     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1534     IWineD3DVertexBuffer     *oldSrc;
1535
1536     oldSrc = This->stateBlock->streamSource[StreamNumber];
1537     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1538
1539     This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1540     This->updateStateBlock->set.streamSource[StreamNumber]     = TRUE;
1541     This->updateStateBlock->streamStride[StreamNumber]         = Stride;
1542     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
1543     This->updateStateBlock->streamOffset[StreamNumber]         = OffsetInBytes;
1544
1545     /* Handle recording of state blocks */
1546     if (This->isRecordingState) {
1547         TRACE("Recording... not performing anything\n");
1548         return D3D_OK;
1549     }
1550
1551     /* Not recording... */
1552     if (pStreamData != NULL) {
1553         IUnknown *newVertexBufferParent;
1554         /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1555         IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1556     }
1557     if (oldSrc != NULL) {
1558         IUnknown *oldVertexBufferParent;
1559         IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1560         IUnknown_Release(oldVertexBufferParent);
1561         IUnknown_Release(oldVertexBufferParent);
1562     }
1563
1564     return D3D_OK;
1565 }
1566
1567 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1568     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1569
1570     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1571     *pStream = This->stateBlock->streamSource[StreamNumber];
1572     *pStride = This->stateBlock->streamStride[StreamNumber];
1573     *pOffset = This->stateBlock->streamOffset[StreamNumber];
1574     if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1575     return D3D_OK;
1576 }
1577
1578 /*Should be quite easy, just an extension of vertexdata
1579 ref...
1580 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1581
1582 The divider is a bit odd though
1583
1584 VertexOffset = StartVertex / Divider * StreamStride +
1585                VertexIndex / Divider * StreamStride + StreamOffset
1586
1587 */
1588 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
1589     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1590
1591     FIXME("(%p) : stub\n", This);
1592     return D3D_OK;
1593 }
1594
1595 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
1596     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1597
1598     FIXME("(%p) : stub\n", This);
1599     return D3D_OK;
1600 }
1601
1602 /*****
1603  * Get / Set & Multiply Transform
1604  *****/
1605 HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1606     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1607
1608     /* Most of this routine, comments included copied from ddraw tree initially: */
1609     TRACE("(%p) : Transform State=%d\n", This, d3dts);
1610
1611     /* Handle recording of state blocks */
1612     if (This->isRecordingState) {
1613         TRACE("Recording... not performing anything\n");
1614         This->updateStateBlock->changed.transform[d3dts] = TRUE;
1615         This->updateStateBlock->set.transform[d3dts]     = TRUE;
1616         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1617         return D3D_OK;
1618     }
1619
1620     /*
1621      * If the new matrix is the same as the current one,
1622      * we cut off any further processing. this seems to be a reasonable
1623      * optimization because as was noticed, some apps (warcraft3 for example)
1624      * tend towards setting the same matrix repeatedly for some reason.
1625      *
1626      * From here on we assume that the new matrix is different, wherever it matters.
1627      */
1628     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1629         TRACE("The app is setting the same matrix over again\n");
1630         return D3D_OK;
1631     } else {
1632         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1633     }
1634
1635     /*
1636        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1637        where ViewMat = Camera space, WorldMat = world space.
1638
1639        In OpenGL, camera and world space is combined into GL_MODELVIEW
1640        matrix.  The Projection matrix stay projection matrix.
1641      */
1642
1643     /* Capture the times we can just ignore the change for now */
1644     if (d3dts == D3DTS_WORLDMATRIX(0)) {
1645         This->modelview_valid = FALSE;
1646         return D3D_OK;
1647
1648     } else if (d3dts == D3DTS_PROJECTION) {
1649         This->proj_valid = FALSE;
1650         return D3D_OK;
1651
1652     } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1653         /* Indexed Vertex Blending Matrices 256 -> 511  */
1654         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1655         FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1656         return D3D_OK;
1657     }
1658
1659     /* Now we really are going to have to change a matrix */
1660     ENTER_GL();
1661
1662     if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1663         /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1664     } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1665         unsigned int k;
1666
1667         /* If we are changing the View matrix, reset the light and clipping planes to the new view
1668          * NOTE: We have to reset the positions even if the light/plane is not currently
1669          *       enabled, since the call to enable it will not reset the position.
1670          * NOTE2: Apparently texture transforms do NOT need reapplying
1671          */
1672
1673         PLIGHTINFOEL *lightChain = NULL;
1674         This->modelview_valid = FALSE;
1675         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1676
1677         glMatrixMode(GL_MODELVIEW);
1678         checkGLcall("glMatrixMode(GL_MODELVIEW)");
1679         glPushMatrix();
1680         glLoadMatrixf((float *)lpmatrix);
1681         checkGLcall("glLoadMatrixf(...)");
1682
1683         /* Reset lights */
1684         lightChain = This->stateBlock->lights;
1685         while (lightChain && lightChain->glIndex != -1) {
1686             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1687             checkGLcall("glLightfv posn");
1688             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1689             checkGLcall("glLightfv dirn");
1690             lightChain = lightChain->next;
1691         }
1692
1693         /* Reset Clipping Planes if clipping is enabled */
1694         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1695             glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1696             checkGLcall("glClipPlane");
1697         }
1698         glPopMatrix();
1699
1700     } else { /* What was requested!?? */
1701         WARN("invalid matrix specified: %i\n", d3dts);
1702     }
1703
1704     /* Release lock, all done */
1705     LEAVE_GL();
1706     return D3D_OK;
1707
1708 }
1709 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1710     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1711     TRACE("(%p) : for Transform State %d\n", This, State);
1712     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1713     return D3D_OK;
1714 }
1715
1716 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1717     D3DMATRIX *mat = NULL;
1718     D3DMATRIX temp;
1719
1720     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1721      * below means it will be recorded in a state block change, but it
1722      * works regardless where it is recorded.
1723      * If this is found to be wrong, change to StateBlock.
1724      */
1725     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1726     TRACE("(%p) : For state %u\n", This, State);
1727
1728     if (State < HIGHEST_TRANSFORMSTATE)
1729     {
1730         mat = &This->updateStateBlock->transforms[State];
1731     } else {
1732         FIXME("Unhandled transform state!!\n");
1733     }
1734
1735     /* Copied from ddraw code:  */
1736     temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) +
1737       (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1738     temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) +
1739       (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1740     temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) +
1741       (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1742     temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) +
1743       (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1744
1745     temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) +
1746       (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1747     temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) +
1748       (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1749     temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) +
1750       (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1751     temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) +
1752       (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1753
1754     temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) +
1755       (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1756     temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) +
1757       (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1758     temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) +
1759       (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1760     temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) +
1761       (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1762
1763     temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) +
1764       (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1765     temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) +
1766       (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1767     temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) +
1768       (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1769     temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) +
1770       (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1771
1772     /* Apply change via set transform - will reapply to eg. lights this way */
1773     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1774 }
1775
1776 /*****
1777  * Get / Set Light
1778  *   WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1779  *****/
1780 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1781    you can reference any indexes you want as long as that number max are enabled at any
1782    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1783    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1784    but when recording, just build a chain pretty much of commands to be replayed.                  */
1785
1786 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1787     float rho;
1788     PLIGHTINFOEL *object, *temp;
1789
1790     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1791     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1792
1793     /* If recording state block, just add to end of lights chain */
1794     if (This->isRecordingState) {
1795         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1796         if (NULL == object) {
1797             return D3DERR_OUTOFVIDEOMEMORY;
1798         }
1799         memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1800         object->OriginalIndex = Index;
1801         object->glIndex = -1;
1802         object->changed = TRUE;
1803
1804         /* Add to the END of the chain of lights changes to be replayed */
1805         if (This->updateStateBlock->lights == NULL) {
1806             This->updateStateBlock->lights = object;
1807         } else {
1808             temp = This->updateStateBlock->lights;
1809             while (temp->next != NULL) temp=temp->next;
1810             temp->next = object;
1811         }
1812         TRACE("Recording... not performing anything more\n");
1813         return D3D_OK;
1814     }
1815
1816     /* Ok, not recording any longer so do real work */
1817     object = This->stateBlock->lights;
1818     while (object != NULL && object->OriginalIndex != Index) object = object->next;
1819
1820     /* If we didn't find it in the list of lights, time to add it */
1821     if (object == NULL) {
1822         PLIGHTINFOEL *insertAt,*prevPos;
1823
1824         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1825         if (NULL == object) {
1826             return D3DERR_OUTOFVIDEOMEMORY;
1827         }
1828         object->OriginalIndex = Index;
1829         object->glIndex = -1;
1830
1831         /* Add it to the front of list with the idea that lights will be changed as needed
1832            BUT after any lights currently assigned GL indexes                             */
1833         insertAt = This->stateBlock->lights;
1834         prevPos  = NULL;
1835         while (insertAt != NULL && insertAt->glIndex != -1) {
1836             prevPos  = insertAt;
1837             insertAt = insertAt->next;
1838         }
1839
1840         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1841             This->stateBlock->lights = object;
1842         } else if (insertAt == NULL) { /* End of list */
1843             prevPos->next = object;
1844             object->prev = prevPos;
1845         } else { /* Middle of chain */
1846             if (prevPos == NULL) {
1847                 This->stateBlock->lights = object;
1848             } else {
1849                 prevPos->next = object;
1850             }
1851             object->prev = prevPos;
1852             object->next = insertAt;
1853             insertAt->prev = object;
1854         }
1855     }
1856
1857     /* Initialze the object */
1858     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,
1859           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1860           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1861           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1862     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1863           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1864     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1865
1866     /* Save away the information */
1867     memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1868
1869     switch (pLight->Type) {
1870     case D3DLIGHT_POINT:
1871         /* Position */
1872         object->lightPosn[0] = pLight->Position.x;
1873         object->lightPosn[1] = pLight->Position.y;
1874         object->lightPosn[2] = pLight->Position.z;
1875         object->lightPosn[3] = 1.0f;
1876         object->cutoff = 180.0f;
1877         /* FIXME: Range */
1878         break;
1879
1880     case D3DLIGHT_DIRECTIONAL:
1881         /* Direction */
1882         object->lightPosn[0] = -pLight->Direction.x;
1883         object->lightPosn[1] = -pLight->Direction.y;
1884         object->lightPosn[2] = -pLight->Direction.z;
1885         object->lightPosn[3] = 0.0;
1886         object->exponent     = 0.0f;
1887         object->cutoff       = 180.0f;
1888         break;
1889
1890     case D3DLIGHT_SPOT:
1891         /* Position */
1892         object->lightPosn[0] = pLight->Position.x;
1893         object->lightPosn[1] = pLight->Position.y;
1894         object->lightPosn[2] = pLight->Position.z;
1895         object->lightPosn[3] = 1.0;
1896
1897         /* Direction */
1898         object->lightDirn[0] = pLight->Direction.x;
1899         object->lightDirn[1] = pLight->Direction.y;
1900         object->lightDirn[2] = pLight->Direction.z;
1901         object->lightDirn[3] = 1.0;
1902
1903         /*
1904          * opengl-ish and d3d-ish spot lights use too different models for the
1905          * light "intensity" as a function of the angle towards the main light direction,
1906          * so we only can approximate very roughly.
1907          * however spot lights are rather rarely used in games (if ever used at all).
1908          * furthermore if still used, probably nobody pays attention to such details.
1909          */
1910         if (pLight->Falloff == 0) {
1911             rho = 6.28f;
1912         } else {
1913             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1914         }
1915         if (rho < 0.0001) rho = 0.0001f;
1916         object->exponent = -0.3/log(cos(rho/2));
1917         object->cutoff = pLight->Phi*90/M_PI;
1918
1919         /* FIXME: Range */
1920         break;
1921
1922     default:
1923         FIXME("Unrecognized light type %d\n", pLight->Type);
1924     }
1925
1926     /* Update the live definitions if the light is currently assigned a glIndex */
1927     if (object->glIndex != -1) {
1928         setup_light(iface, object->glIndex, object);
1929     }
1930     return D3D_OK;
1931 }
1932
1933 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1934     PLIGHTINFOEL *lightInfo = NULL;
1935     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1936     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1937
1938     /* Locate the light in the live lights */
1939     lightInfo = This->stateBlock->lights;
1940     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1941
1942     if (lightInfo == NULL) {
1943         TRACE("Light information requested but light not defined\n");
1944         return D3DERR_INVALIDCALL;
1945     }
1946
1947     memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1948     return D3D_OK;
1949 }
1950
1951 /*****
1952  * Get / Set Light Enable
1953  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1954  *****/
1955 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1956     PLIGHTINFOEL *lightInfo = NULL;
1957     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1958     TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1959
1960     /* If recording state block, just add to end of lights chain with changedEnable set to true */
1961     if (This->isRecordingState) {
1962         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1963         if (NULL == lightInfo) {
1964             return D3DERR_OUTOFVIDEOMEMORY;
1965         }
1966         lightInfo->OriginalIndex = Index;
1967         lightInfo->glIndex = -1;
1968         lightInfo->enabledChanged = TRUE;
1969
1970         /* Add to the END of the chain of lights changes to be replayed */
1971         if (This->updateStateBlock->lights == NULL) {
1972             This->updateStateBlock->lights = lightInfo;
1973         } else {
1974             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1975             while (temp->next != NULL) temp=temp->next;
1976             temp->next = lightInfo;
1977         }
1978         TRACE("Recording... not performing anything more\n");
1979         return D3D_OK;
1980     }
1981
1982     /* Not recording... So, locate the light in the live lights */
1983     lightInfo = This->stateBlock->lights;
1984     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1985
1986     /* Special case - enabling an undefined light creates one with a strict set of parms! */
1987     if (lightInfo == NULL) {
1988         D3DLIGHT9 lightParms;
1989         /* Warning - untested code :-) Prob safe to change fixme to a trace but
1990              wait until someone confirms it seems to work!                     */
1991         TRACE("Light enabled requested but light not defined, so defining one!\n");
1992         lightParms.Type         = D3DLIGHT_DIRECTIONAL;
1993         lightParms.Diffuse.r    = 1.0;
1994         lightParms.Diffuse.g    = 1.0;
1995         lightParms.Diffuse.b    = 1.0;
1996         lightParms.Diffuse.a    = 0.0;
1997         lightParms.Specular.r   = 0.0;
1998         lightParms.Specular.g   = 0.0;
1999         lightParms.Specular.b   = 0.0;
2000         lightParms.Specular.a   = 0.0;
2001         lightParms.Ambient.r    = 0.0;
2002         lightParms.Ambient.g    = 0.0;
2003         lightParms.Ambient.b    = 0.0;
2004         lightParms.Ambient.a    = 0.0;
2005         lightParms.Position.x   = 0.0;
2006         lightParms.Position.y   = 0.0;
2007         lightParms.Position.z   = 0.0;
2008         lightParms.Direction.x  = 0.0;
2009         lightParms.Direction.y  = 0.0;
2010         lightParms.Direction.z  = 1.0;
2011         lightParms.Range        = 0.0;
2012         lightParms.Falloff      = 0.0;
2013         lightParms.Attenuation0 = 0.0;
2014         lightParms.Attenuation1 = 0.0;
2015         lightParms.Attenuation2 = 0.0;
2016         lightParms.Theta        = 0.0;
2017         lightParms.Phi          = 0.0;
2018         IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2019
2020         /* Search for it again! Should be fairly quick as near head of list */
2021         lightInfo = This->stateBlock->lights;
2022         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2023         if (lightInfo == NULL) {
2024             FIXME("Adding default lights has failed dismally\n");
2025             return D3DERR_INVALIDCALL;
2026         }
2027     }
2028
2029     /* OK, we now have a light... */
2030     if (Enable == FALSE) {
2031
2032         /* If we are disabling it, check it was enabled, and
2033            still only do something if it has assigned a glIndex (which it should have!)   */
2034         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2035             TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2036             ENTER_GL();
2037             glDisable(GL_LIGHT0 + lightInfo->glIndex);
2038             checkGLcall("glDisable GL_LIGHT0+Index");
2039             LEAVE_GL();
2040         } else {
2041             TRACE("Nothing to do as light was not enabled\n");
2042         }
2043         lightInfo->lightEnabled = FALSE;
2044     } else {
2045
2046         /* We are enabling it. If it is enabled, it's really simple */
2047         if (lightInfo->lightEnabled) {
2048             /* nop */
2049             TRACE("Nothing to do as light was enabled\n");
2050
2051         /* If it already has a glIndex, it's still simple */
2052         } else if (lightInfo->glIndex != -1) {
2053             TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2054             lightInfo->lightEnabled = TRUE;
2055             ENTER_GL();
2056             glEnable(GL_LIGHT0 + lightInfo->glIndex);
2057             checkGLcall("glEnable GL_LIGHT0+Index already setup");
2058             LEAVE_GL();
2059
2060         /* Otherwise got to find space - lights are ordered gl indexes first */
2061         } else {
2062             PLIGHTINFOEL *bsf  = NULL;
2063             PLIGHTINFOEL *pos  = This->stateBlock->lights;
2064             PLIGHTINFOEL *prev = NULL;
2065             int           Index= 0;
2066             int           glIndex = -1;
2067
2068             /* Try to minimize changes as much as possible */
2069             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2070
2071                 /* Try to remember which index can be replaced if necessary */
2072                 if (bsf==NULL && pos->lightEnabled == FALSE) {
2073                     /* Found a light we can replace, save as best replacement */
2074                     bsf = pos;
2075                 }
2076
2077                 /* Step to next space */
2078                 prev = pos;
2079                 pos = pos->next;
2080                 Index ++;
2081             }
2082
2083             /* If we have too many active lights, fail the call */
2084             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2085                 FIXME("Program requests too many concurrent lights\n");
2086                 return D3DERR_INVALIDCALL;
2087
2088             /* If we have allocated all lights, but not all are enabled,
2089                reuse one which is not enabled                           */
2090             } else if (Index == This->maxConcurrentLights) {
2091                 /* use bsf - Simply swap the new light and the BSF one */
2092                 PLIGHTINFOEL *bsfNext = bsf->next;
2093                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2094
2095                 /* Sort out ends */
2096                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2097                 if (bsf->prev != NULL) {
2098                     bsf->prev->next = lightInfo;
2099                 } else {
2100                     This->stateBlock->lights = lightInfo;
2101                 }
2102
2103                 /* If not side by side, lots of chains to update */
2104                 if (bsf->next != lightInfo) {
2105                     lightInfo->prev->next = bsf;
2106                     bsf->next->prev = lightInfo;
2107                     bsf->next       = lightInfo->next;
2108                     bsf->prev       = lightInfo->prev;
2109                     lightInfo->next = bsfNext;
2110                     lightInfo->prev = bsfPrev;
2111
2112                 } else {
2113                     /* Simple swaps */
2114                     bsf->prev = lightInfo;
2115                     bsf->next = lightInfo->next;
2116                     lightInfo->next = bsf;
2117                     lightInfo->prev = bsfPrev;
2118                 }
2119
2120
2121                 /* Update states */
2122                 glIndex = bsf->glIndex;
2123                 bsf->glIndex = -1;
2124                 lightInfo->glIndex = glIndex;
2125                 lightInfo->lightEnabled = TRUE;
2126
2127                 /* Finally set up the light in gl itself */
2128                 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2129                 ENTER_GL();
2130                 setup_light(iface, glIndex, lightInfo);
2131                 glEnable(GL_LIGHT0 + glIndex);
2132                 checkGLcall("glEnable GL_LIGHT0 new setup");
2133                 LEAVE_GL();
2134
2135             /* If we reached the end of the allocated lights, with space in the
2136                gl lights, setup a new light                                     */
2137             } else if (pos->glIndex == -1) {
2138
2139                 /* We reached the end of the allocated gl lights, so already
2140                     know the index of the next one!                          */
2141                 glIndex = Index;
2142                 lightInfo->glIndex = glIndex;
2143                 lightInfo->lightEnabled = TRUE;
2144
2145                 /* In an ideal world, it's already in the right place */
2146                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2147                    /* No need to move it */
2148                 } else {
2149                     /* Remove this light from the list */
2150                     lightInfo->prev->next = lightInfo->next;
2151                     if (lightInfo->next != NULL) {
2152                         lightInfo->next->prev = lightInfo->prev;
2153                     }
2154
2155                     /* Add in at appropriate place (inbetween prev and pos) */
2156                     lightInfo->prev = prev;
2157                     lightInfo->next = pos;
2158                     if (prev == NULL) {
2159                         This->stateBlock->lights = lightInfo;
2160                     } else {
2161                         prev->next = lightInfo;
2162                     }
2163                     if (pos != NULL) {
2164                         pos->prev = lightInfo;
2165                     }
2166                 }
2167
2168                 /* Finally set up the light in gl itself */
2169                 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2170                 ENTER_GL();
2171                 setup_light(iface, glIndex, lightInfo);
2172                 glEnable(GL_LIGHT0 + glIndex);
2173                 checkGLcall("glEnable GL_LIGHT0 new setup");
2174                 LEAVE_GL();
2175
2176             }
2177         }
2178     }
2179     return D3D_OK;
2180 }
2181
2182 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2183
2184     PLIGHTINFOEL *lightInfo = NULL;
2185     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2186     TRACE("(%p) : for idx(%ld)\n", This, Index);
2187
2188     /* Locate the light in the live lights */
2189     lightInfo = This->stateBlock->lights;
2190     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2191
2192     if (lightInfo == NULL) {
2193         TRACE("Light enabled state requested but light not defined\n");
2194         return D3DERR_INVALIDCALL;
2195     }
2196     *pEnable = lightInfo->lightEnabled;
2197     return D3D_OK;
2198 }
2199
2200 /*****
2201  * Get / Set Clip Planes
2202  *****/
2203 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2204     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2205     TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2206
2207     /* Validate Index */
2208     if (Index >= GL_LIMITS(clipplanes)) {
2209         TRACE("Application has requested clipplane this device doesn't support\n");
2210         return D3DERR_INVALIDCALL;
2211     }
2212
2213     This->updateStateBlock->changed.clipplane[Index] = TRUE;
2214     This->updateStateBlock->set.clipplane[Index] = TRUE;
2215     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2216     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2217     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2218     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2219
2220     /* Handle recording of state blocks */
2221     if (This->isRecordingState) {
2222         TRACE("Recording... not performing anything\n");
2223         return D3D_OK;
2224     }
2225
2226     /* Apply it */
2227
2228     ENTER_GL();
2229
2230     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2231     glMatrixMode(GL_MODELVIEW);
2232     glPushMatrix();
2233     glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2234
2235     TRACE("Clipplane [%f,%f,%f,%f]\n",
2236           This->updateStateBlock->clipplane[Index][0],
2237           This->updateStateBlock->clipplane[Index][1],
2238           This->updateStateBlock->clipplane[Index][2],
2239           This->updateStateBlock->clipplane[Index][3]);
2240     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2241     checkGLcall("glClipPlane");
2242
2243     glPopMatrix();
2244     LEAVE_GL();
2245
2246     return D3D_OK;
2247 }
2248
2249 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2250     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2251     TRACE("(%p) : for idx %ld\n", This, Index);
2252
2253     /* Validate Index */
2254     if (Index >= GL_LIMITS(clipplanes)) {
2255         TRACE("Application has requested clipplane this device doesn't support\n");
2256         return D3DERR_INVALIDCALL;
2257     }
2258
2259     pPlane[0] = This->stateBlock->clipplane[Index][0];
2260     pPlane[1] = This->stateBlock->clipplane[Index][1];
2261     pPlane[2] = This->stateBlock->clipplane[Index][2];
2262     pPlane[3] = This->stateBlock->clipplane[Index][3];
2263     return D3D_OK;
2264 }
2265
2266 /*****
2267  * Get / Set Clip Plane Status
2268  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2269  *****/
2270 HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2271     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2272     FIXME("(%p) : stub\n", This);
2273     if (NULL == pClipStatus) {
2274       return D3DERR_INVALIDCALL;
2275     }
2276     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2277     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2278     return D3D_OK;
2279 }
2280
2281 HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2282     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2283     FIXME("(%p) : stub\n", This);
2284     if (NULL == pClipStatus) {
2285       return D3DERR_INVALIDCALL;
2286     }
2287     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2288     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2289     return D3D_OK;
2290 }
2291
2292 /*****
2293  * Get / Set Material
2294  *   WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2295  *****/
2296 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2297     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2298
2299     This->updateStateBlock->changed.material = TRUE;
2300     This->updateStateBlock->set.material = TRUE;
2301     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2302
2303     /* Handle recording of state blocks */
2304     if (This->isRecordingState) {
2305         TRACE("Recording... not performing anything\n");
2306         return D3D_OK;
2307     }
2308
2309     ENTER_GL();
2310     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2311         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2312     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2313         pMaterial->Ambient.b, pMaterial->Ambient.a);
2314     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2315         pMaterial->Specular.b, pMaterial->Specular.a);
2316     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2317         pMaterial->Emissive.b, pMaterial->Emissive.a);
2318     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2319
2320     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2321     checkGLcall("glMaterialfv(GL_AMBIENT)");
2322     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2323     checkGLcall("glMaterialfv(GL_DIFFUSE)");
2324
2325     /* Only change material color if specular is enabled, otherwise it is set to black */
2326     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2327        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2328        checkGLcall("glMaterialfv(GL_SPECULAR");
2329     } else {
2330        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2331        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2332        checkGLcall("glMaterialfv(GL_SPECULAR");
2333     }
2334     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2335     checkGLcall("glMaterialfv(GL_EMISSION)");
2336     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2337     checkGLcall("glMaterialf(GL_SHININESS");
2338
2339     LEAVE_GL();
2340     return D3D_OK;
2341 }
2342
2343 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2344     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2345     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2346     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2347         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2348     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2349         pMaterial->Ambient.b, pMaterial->Ambient.a);
2350     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2351         pMaterial->Specular.b, pMaterial->Specular.a);
2352     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2353         pMaterial->Emissive.b, pMaterial->Emissive.a);
2354     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2355
2356     return D3D_OK;
2357 }
2358
2359 /*****
2360  * Get / Set Indices
2361  *****/
2362 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2363                                              UINT BaseVertexIndex) {
2364     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
2365     IWineD3DIndexBuffer *oldIdxs;
2366
2367     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2368     oldIdxs = This->updateStateBlock->pIndexData;
2369
2370     This->updateStateBlock->changed.indices = TRUE;
2371     This->updateStateBlock->set.indices = TRUE;
2372     This->updateStateBlock->pIndexData = pIndexData;
2373     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2374
2375     /* Handle recording of state blocks */
2376     if (This->isRecordingState) {
2377         TRACE("Recording... not performing anything\n");
2378         return D3D_OK;
2379     }
2380
2381     if (pIndexData) {
2382         IUnknown *indexBufferParent;
2383         /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2384         IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2385     }
2386     if (oldIdxs) {
2387         IUnknown *indexBufferParent;
2388         IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2389         IUnknown_Release(indexBufferParent);
2390         IUnknown_Release(indexBufferParent);
2391     }
2392     return D3D_OK;
2393 }
2394
2395 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2396     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2397
2398     *ppIndexData = This->stateBlock->pIndexData;
2399
2400     /* up ref count on ppindexdata */
2401     if (*ppIndexData) {
2402         IWineD3DIndexBuffer_AddRef(*ppIndexData);
2403         *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2404         TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2405     }else{
2406         TRACE("(%p) No index data set\n", This);
2407     }
2408     TRACE("Returning %p %d \n",*ppIndexData, *pBaseVertexIndex);
2409
2410     return D3D_OK;
2411 }
2412
2413 /*****
2414  * Get / Set Viewports
2415  *****/
2416 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2417     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2418
2419     TRACE("(%p)\n", This);
2420     This->updateStateBlock->changed.viewport = TRUE;
2421     This->updateStateBlock->set.viewport = TRUE;
2422     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2423
2424     /* Handle recording of state blocks */
2425     if (This->isRecordingState) {
2426         TRACE("Recording... not performing anything\n");
2427         return D3D_OK;
2428     }
2429
2430     ENTER_GL();
2431
2432     TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2433           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2434
2435     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2436     checkGLcall("glDepthRange");
2437     /* Note: GL requires lower left, DirectX supplies upper left */
2438     /* TODO: replace usage of renderTarget with context management */
2439     glViewport(pViewport->X,
2440                (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2441                pViewport->Width, pViewport->Height);
2442
2443     checkGLcall("glViewport");
2444
2445     LEAVE_GL();
2446
2447     return D3D_OK;
2448
2449 }
2450
2451 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2452     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2453     TRACE("(%p)\n", This);
2454     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2455     return D3D_OK;
2456 }
2457
2458 /*****
2459  * Get / Set Render States
2460  * TODO: Verify against dx9 definitions
2461  *****/
2462 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2463
2464     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
2465     DWORD                OldValue = This->stateBlock->renderState[State];
2466
2467     /* Simple way of referring to either a DWORD or a 4 byte float */
2468     union {
2469         DWORD d;
2470         float f;
2471     } tmpvalue;
2472
2473     TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2474     This->updateStateBlock->changed.renderState[State] = TRUE;
2475     This->updateStateBlock->set.renderState[State] = TRUE;
2476     This->updateStateBlock->renderState[State] = Value;
2477
2478     /* Handle recording of state blocks */
2479     if (This->isRecordingState) {
2480         TRACE("Recording... not performing anything\n");
2481         return D3D_OK;
2482     }
2483
2484     ENTER_GL();
2485
2486     switch (State) {
2487     case WINED3DRS_FILLMODE                  :
2488         switch ((D3DFILLMODE) Value) {
2489         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2490         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2491         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2492         default:
2493             FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2494         }
2495         checkGLcall("glPolygonMode (fillmode)");
2496         break;
2497
2498     case WINED3DRS_LIGHTING                  :
2499         if (Value) {
2500             glEnable(GL_LIGHTING);
2501             checkGLcall("glEnable GL_LIGHTING");
2502         } else {
2503             glDisable(GL_LIGHTING);
2504             checkGLcall("glDisable GL_LIGHTING");
2505         }
2506         break;
2507
2508     case WINED3DRS_ZENABLE                   :
2509         switch ((D3DZBUFFERTYPE) Value) {
2510         case D3DZB_FALSE:
2511             glDisable(GL_DEPTH_TEST);
2512             checkGLcall("glDisable GL_DEPTH_TEST");
2513             break;
2514         case D3DZB_TRUE:
2515             glEnable(GL_DEPTH_TEST);
2516             checkGLcall("glEnable GL_DEPTH_TEST");
2517             break;
2518         case D3DZB_USEW:
2519             glEnable(GL_DEPTH_TEST);
2520             checkGLcall("glEnable GL_DEPTH_TEST");
2521             FIXME("W buffer is not well handled\n");
2522             break;
2523         default:
2524             FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2525         }
2526         break;
2527
2528     case WINED3DRS_CULLMODE                  :
2529
2530         /* If we are culling "back faces with clockwise vertices" then
2531            set front faces to be counter clockwise and enable culling
2532            of back faces                                               */
2533         switch ((D3DCULL) Value) {
2534         case D3DCULL_NONE:
2535             glDisable(GL_CULL_FACE);
2536             checkGLcall("glDisable GL_CULL_FACE");
2537             break;
2538         case D3DCULL_CW:
2539             glEnable(GL_CULL_FACE);
2540             checkGLcall("glEnable GL_CULL_FACE");
2541             if (This->renderUpsideDown) {
2542                 glFrontFace(GL_CW);
2543                 checkGLcall("glFrontFace GL_CW");
2544             } else {
2545                 glFrontFace(GL_CCW);
2546                 checkGLcall("glFrontFace GL_CCW");
2547             }
2548             glCullFace(GL_BACK);
2549             break;
2550         case D3DCULL_CCW:
2551             glEnable(GL_CULL_FACE);
2552             checkGLcall("glEnable GL_CULL_FACE");
2553             if (This->renderUpsideDown) {
2554                 glFrontFace(GL_CCW);
2555                 checkGLcall("glFrontFace GL_CCW");
2556             } else {
2557                 glFrontFace(GL_CW);
2558                 checkGLcall("glFrontFace GL_CW");
2559             }
2560             glCullFace(GL_BACK);
2561             break;
2562         default:
2563             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2564         }
2565         break;
2566
2567     case WINED3DRS_SHADEMODE                 :
2568         switch ((D3DSHADEMODE) Value) {
2569         case D3DSHADE_FLAT:
2570             glShadeModel(GL_FLAT);
2571             checkGLcall("glShadeModel");
2572             break;
2573         case D3DSHADE_GOURAUD:
2574             glShadeModel(GL_SMOOTH);
2575             checkGLcall("glShadeModel");
2576             break;
2577         case D3DSHADE_PHONG:
2578             FIXME("D3DSHADE_PHONG isn't supported?\n");
2579
2580             LEAVE_GL();
2581             return D3DERR_INVALIDCALL;
2582         default:
2583             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2584         }
2585         break;
2586
2587     case WINED3DRS_DITHERENABLE              :
2588         if (Value) {
2589             glEnable(GL_DITHER);
2590             checkGLcall("glEnable GL_DITHER");
2591         } else {
2592             glDisable(GL_DITHER);
2593             checkGLcall("glDisable GL_DITHER");
2594         }
2595         break;
2596
2597     case WINED3DRS_ZWRITEENABLE              :
2598         if (Value) {
2599             glDepthMask(1);
2600             checkGLcall("glDepthMask");
2601         } else {
2602             glDepthMask(0);
2603             checkGLcall("glDepthMask");
2604         }
2605         break;
2606
2607     case WINED3DRS_ZFUNC                     :
2608         {
2609             int glParm = GL_LESS;
2610
2611             switch ((D3DCMPFUNC) Value) {
2612             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2613             case D3DCMP_LESS:          glParm=GL_LESS; break;
2614             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2615             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2616             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2617             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2618             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2619             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2620             default:
2621                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2622             }
2623             glDepthFunc(glParm);
2624             checkGLcall("glDepthFunc");
2625         }
2626         break;
2627
2628     case WINED3DRS_AMBIENT                   :
2629         {
2630             float col[4];
2631             D3DCOLORTOGLFLOAT4(Value, col);
2632             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2633             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2634             checkGLcall("glLightModel for MODEL_AMBIENT");
2635
2636         }
2637         break;
2638
2639     case WINED3DRS_ALPHABLENDENABLE          :
2640         if (Value) {
2641             glEnable(GL_BLEND);
2642             checkGLcall("glEnable GL_BLEND");
2643         } else {
2644             glDisable(GL_BLEND);
2645             checkGLcall("glDisable GL_BLEND");
2646         };
2647         break;
2648
2649     case WINED3DRS_SRCBLEND                  :
2650     case WINED3DRS_DESTBLEND                 :
2651         {
2652             int newVal = GL_ZERO;
2653             switch (Value) {
2654             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
2655             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
2656             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
2657             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
2658             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
2659             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
2660             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
2661             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
2662             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
2663             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
2664             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
2665
2666             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
2667                 This->srcBlend = newVal;
2668                 This->dstBlend = newVal;
2669                 break;
2670
2671             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
2672                 This->srcBlend = newVal;
2673                 This->dstBlend = newVal;
2674                 break;
2675             default:
2676                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2677             }
2678
2679             if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2680             if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2681             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2682             glBlendFunc(This->srcBlend, This->dstBlend);
2683
2684             checkGLcall("glBlendFunc");
2685         }
2686         break;
2687
2688     case WINED3DRS_ALPHATESTENABLE           :
2689         if (Value) {
2690             glEnable(GL_ALPHA_TEST);
2691             checkGLcall("glEnable GL_ALPHA_TEST");
2692         } else {
2693             glDisable(GL_ALPHA_TEST);
2694             checkGLcall("glDisable GL_ALPHA_TEST");
2695         }
2696         break;
2697
2698     case WINED3DRS_ALPHAFUNC                 :
2699         {
2700             int glParm = GL_LESS;
2701             float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2702
2703             switch ((D3DCMPFUNC) Value) {
2704             case D3DCMP_NEVER:         glParm = GL_NEVER; break;
2705             case D3DCMP_LESS:          glParm = GL_LESS; break;
2706             case D3DCMP_EQUAL:         glParm = GL_EQUAL; break;
2707             case D3DCMP_LESSEQUAL:     glParm = GL_LEQUAL; break;
2708             case D3DCMP_GREATER:       glParm = GL_GREATER; break;
2709             case D3DCMP_NOTEQUAL:      glParm = GL_NOTEQUAL; break;
2710             case D3DCMP_GREATEREQUAL:  glParm = GL_GEQUAL; break;
2711             case D3DCMP_ALWAYS:        glParm = GL_ALWAYS; break;
2712             default:
2713                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2714             }
2715             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2716             glAlphaFunc(glParm, ref);
2717             This->alphafunc = glParm;
2718             checkGLcall("glAlphaFunc");
2719         }
2720         break;
2721
2722     case WINED3DRS_ALPHAREF                  :
2723         {
2724             int glParm = This->alphafunc;
2725             float ref = 1.0f;
2726
2727             ref = ((float) Value) / 255.0f;
2728             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2729             glAlphaFunc(glParm, ref);
2730             checkGLcall("glAlphaFunc");
2731         }
2732         break;
2733
2734     case WINED3DRS_CLIPPLANEENABLE           :
2735     case WINED3DRS_CLIPPING                  :
2736         {
2737             /* Ensure we only do the changed clip planes */
2738             DWORD enable  = 0xFFFFFFFF;
2739             DWORD disable = 0x00000000;
2740
2741             /* If enabling / disabling all */
2742             if (State == WINED3DRS_CLIPPING) {
2743                 if (Value) {
2744                     enable  = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2745                     disable = 0x00;
2746                 } else {
2747                     disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2748                     enable  = 0x00;
2749                 }
2750             } else {
2751                 enable =   Value & ~OldValue;
2752                 disable = ~Value &  OldValue;
2753             }
2754
2755             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
2756             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
2757             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
2758             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
2759             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
2760             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
2761
2762             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2763             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2764             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2765             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2766             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2767             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2768
2769             /** update clipping status */
2770             if (enable) {
2771               This->stateBlock->clip_status.ClipUnion = 0;
2772               This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2773             } else {
2774               This->stateBlock->clip_status.ClipUnion = 0;
2775               This->stateBlock->clip_status.ClipIntersection = 0;
2776             }
2777         }
2778         break;
2779
2780     case WINED3DRS_BLENDOP                   :
2781         {
2782             int glParm = GL_FUNC_ADD;
2783
2784             switch ((D3DBLENDOP) Value) {
2785             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
2786             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
2787             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2788             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
2789             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
2790             default:
2791                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2792             }
2793             TRACE("glBlendEquation(%x)\n", glParm);
2794             glBlendEquation(glParm);
2795             checkGLcall("glBlendEquation");
2796         }
2797         break;
2798
2799     case WINED3DRS_TEXTUREFACTOR             :
2800         {
2801             unsigned int i;
2802
2803             /* Note the texture color applies to all textures whereas
2804                GL_TEXTURE_ENV_COLOR applies to active only */
2805             float col[4];
2806             D3DCOLORTOGLFLOAT4(Value, col);
2807             /* Set the default alpha blend color */
2808             glBlendColor(col[0], col[1], col[2], col[3]);
2809             checkGLcall("glBlendColor");
2810
2811             /* And now the default texture color as well */
2812             for (i = 0; i < GL_LIMITS(textures); i++) {
2813
2814                 /* Note the D3DRS value applies to all textures, but GL has one
2815                    per texture, so apply it now ready to be used!               */
2816                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2817                     GLACTIVETEXTURE(i);
2818                 } else if (i>0) {
2819                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2820                 }
2821
2822                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2823                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2824             }
2825         }
2826         break;
2827
2828     case WINED3DRS_SPECULARENABLE            :
2829         {
2830             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2831                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2832                specular color. This is wrong:
2833                Separate specular color means the specular colour is maintained separately, whereas
2834                single color means it is merged in. However in both cases they are being used to
2835                some extent.
2836                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2837                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2838                   running 1.4 yet!
2839              */
2840               if (Value) {
2841                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2842                 checkGLcall("glMaterialfv");
2843                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2844                   glEnable(GL_COLOR_SUM_EXT);
2845                 } else {
2846                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
2847                 }
2848                 checkGLcall("glEnable(GL_COLOR_SUM)");
2849               } else {
2850                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2851
2852                 /* for the case of enabled lighting: */
2853                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2854                 checkGLcall("glMaterialfv");
2855
2856                 /* for the case of disabled lighting: */
2857                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2858                   glDisable(GL_COLOR_SUM_EXT);
2859                 } else {
2860                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
2861                 }
2862                 checkGLcall("glDisable(GL_COLOR_SUM)");
2863               }
2864         }
2865         break;
2866
2867     case WINED3DRS_STENCILENABLE             :
2868         if (Value) {
2869             glEnable(GL_STENCIL_TEST);
2870             checkGLcall("glEnable GL_STENCIL_TEST");
2871         } else {
2872             glDisable(GL_STENCIL_TEST);
2873             checkGLcall("glDisable GL_STENCIL_TEST");
2874         }
2875         break;
2876
2877     case WINED3DRS_STENCILFUNC               :
2878         {
2879            int glParm = GL_ALWAYS;
2880            int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2881            GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2882
2883            switch ((D3DCMPFUNC) Value) {
2884            case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2885            case D3DCMP_LESS:          glParm=GL_LESS; break;
2886            case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2887            case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2888            case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2889            case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2890            case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2891            case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2892            default:
2893                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2894            }
2895            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2896            This->stencilfunc = glParm;
2897            glStencilFunc(glParm, ref, mask);
2898            checkGLcall("glStencilFunc");
2899         }
2900         break;
2901
2902     case WINED3DRS_STENCILREF                :
2903         {
2904            int glParm = This->stencilfunc;
2905            int ref = 0;
2906            GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2907
2908            ref = Value;
2909            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2910            glStencilFunc(glParm, ref, mask);
2911            checkGLcall("glStencilFunc");
2912         }
2913         break;
2914
2915     case WINED3DRS_STENCILMASK               :
2916         {
2917            int glParm = This->stencilfunc;
2918            int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2919            GLuint mask = Value;
2920
2921            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2922            glStencilFunc(glParm, ref, mask);
2923            checkGLcall("glStencilFunc");
2924         }
2925         break;
2926
2927     case WINED3DRS_STENCILFAIL               :
2928         {
2929             GLenum fail  ;
2930             GLint  zpass ;
2931             GLint  zfail ;
2932
2933             fail = StencilOp(Value);
2934             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2935             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2936             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2937             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2938
2939             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2940             glStencilOp(fail, zfail, zpass);
2941             checkGLcall("glStencilOp(fail, zfail, zpass);");
2942         }
2943         break;
2944     case WINED3DRS_STENCILZFAIL              :
2945         {
2946             GLint  fail  ;
2947             GLint  zpass ;
2948             GLenum zfail ;
2949
2950             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2951             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2952             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2953             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2954             zfail = StencilOp(Value);
2955
2956             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2957             glStencilOp(fail, zfail, zpass);
2958             checkGLcall("glStencilOp(fail, zfail, zpass);");
2959         }
2960         break;
2961     case WINED3DRS_STENCILPASS               :
2962         {
2963             GLint  fail  ;
2964             GLenum zpass ;
2965             GLint  zfail ;
2966
2967             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2968             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2969             zpass = StencilOp(Value);
2970             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2971             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2972
2973             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2974             glStencilOp(fail, zfail, zpass);
2975             checkGLcall("glStencilOp(fail, zfail, zpass);");
2976         }
2977         break;
2978
2979     case WINED3DRS_STENCILWRITEMASK          :
2980         {
2981             glStencilMask(Value);
2982             TRACE("glStencilMask(%lu)\n", Value);
2983             checkGLcall("glStencilMask");
2984         }
2985         break;
2986
2987     case WINED3DRS_FOGENABLE                 :
2988         {
2989           if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2990                glEnable(GL_FOG);
2991                checkGLcall("glEnable GL_FOG");
2992             } else {
2993                glDisable(GL_FOG);
2994                checkGLcall("glDisable GL_FOG");
2995             }
2996         }
2997         break;
2998
2999     case WINED3DRS_RANGEFOGENABLE            :
3000         {
3001             if (Value) {
3002               TRACE("Enabled RANGEFOG");
3003             } else {
3004               TRACE("Disabled RANGEFOG");
3005             }
3006         }
3007         break;
3008
3009     case WINED3DRS_FOGCOLOR                  :
3010         {
3011             float col[4];
3012             D3DCOLORTOGLFLOAT4(Value, col);
3013             /* Set the default alpha blend color */
3014             glFogfv(GL_FOG_COLOR, &col[0]);
3015             checkGLcall("glFog GL_FOG_COLOR");
3016         }
3017         break;
3018
3019     case WINED3DRS_FOGTABLEMODE              :
3020         {
3021           glHint(GL_FOG_HINT, GL_NICEST);
3022           switch (Value) {
3023           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3024           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3025           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3026           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3027           default:
3028             FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3029           }
3030           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3031             glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3032           }
3033         }
3034         break;
3035
3036     case WINED3DRS_FOGVERTEXMODE             :
3037         {
3038           glHint(GL_FOG_HINT, GL_FASTEST);
3039           switch (Value) {
3040           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3041           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3042           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3043           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3044           default:
3045             FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3046           }
3047           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3048             glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3049           }
3050         }
3051         break;
3052
3053     case WINED3DRS_FOGSTART                  :
3054         {
3055             tmpvalue.d = Value;
3056             glFogfv(GL_FOG_START, &tmpvalue.f);
3057             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3058             TRACE("Fog Start == %f\n", tmpvalue.f);
3059         }
3060         break;
3061
3062     case WINED3DRS_FOGEND                    :
3063         {
3064             tmpvalue.d = Value;
3065             glFogfv(GL_FOG_END, &tmpvalue.f);
3066             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3067             TRACE("Fog End == %f\n", tmpvalue.f);
3068         }
3069         break;
3070
3071     case WINED3DRS_FOGDENSITY                :
3072         {
3073             tmpvalue.d = Value;
3074             glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3075             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3076         }
3077         break;
3078
3079     case WINED3DRS_VERTEXBLEND               :
3080         {
3081           This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3082           TRACE("Vertex Blending state to %ld\n",  Value);
3083         }
3084         break;
3085
3086     case WINED3DRS_TWEENFACTOR               :
3087         {
3088           tmpvalue.d = Value;
3089           This->updateStateBlock->tween_factor = tmpvalue.f;
3090           TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3091         }
3092         break;
3093
3094     case WINED3DRS_INDEXEDVERTEXBLENDENABLE  :
3095         {
3096           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3097         }
3098         break;
3099
3100     case WINED3DRS_COLORVERTEX               :
3101     case WINED3DRS_DIFFUSEMATERIALSOURCE     :
3102     case WINED3DRS_SPECULARMATERIALSOURCE    :
3103     case WINED3DRS_AMBIENTMATERIALSOURCE     :
3104     case WINED3DRS_EMISSIVEMATERIALSOURCE    :
3105         {
3106             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3107
3108             if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3109                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3110                       This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3111                       This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3112                       This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3113                       This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3114
3115                 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3116                     if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3117                         Parm = GL_AMBIENT_AND_DIFFUSE;
3118                     } else {
3119                         Parm = GL_DIFFUSE;
3120                     }
3121                 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3122                     Parm = GL_AMBIENT;
3123                 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3124                     Parm = GL_EMISSION;
3125                 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3126                     Parm = GL_SPECULAR;
3127                 } else {
3128                     Parm = -1;
3129                 }
3130
3131                 if (Parm == -1) {
3132                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3133                 } else {
3134                     This->tracking_color = NEEDS_TRACKING;
3135                     This->tracking_parm  = Parm;
3136                 }
3137
3138             } else {
3139                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3140             }
3141         }
3142         break;
3143
3144     case WINED3DRS_LINEPATTERN               :
3145         {
3146             union {
3147                 DWORD                 d;
3148                 D3DLINEPATTERN        lp;
3149             } tmppattern;
3150             tmppattern.d = Value;
3151
3152             TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3153
3154             if (tmppattern.lp.wRepeatFactor) {
3155                 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3156                 checkGLcall("glLineStipple(repeat, linepattern)");
3157                 glEnable(GL_LINE_STIPPLE);
3158                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3159             } else {
3160                 glDisable(GL_LINE_STIPPLE);
3161                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3162             }
3163         }
3164         break;
3165
3166     case WINED3DRS_ZBIAS                     : /* D3D8 only */
3167         {
3168             if (Value) {
3169                 tmpvalue.d = Value;
3170                 TRACE("ZBias value %f\n", tmpvalue.f);
3171                 glPolygonOffset(0, -tmpvalue.f);
3172                 checkGLcall("glPolygonOffset(0, -Value)");
3173                 glEnable(GL_POLYGON_OFFSET_FILL);
3174                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3175                 glEnable(GL_POLYGON_OFFSET_LINE);
3176                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3177                 glEnable(GL_POLYGON_OFFSET_POINT);
3178                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3179             } else {
3180                 glDisable(GL_POLYGON_OFFSET_FILL);
3181                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3182                 glDisable(GL_POLYGON_OFFSET_LINE);
3183                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3184                 glDisable(GL_POLYGON_OFFSET_POINT);
3185                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3186             }
3187         }
3188         break;
3189
3190     case WINED3DRS_NORMALIZENORMALS          :
3191         if (Value) {
3192             glEnable(GL_NORMALIZE);
3193             checkGLcall("glEnable(GL_NORMALIZE);");
3194         } else {
3195             glDisable(GL_NORMALIZE);
3196             checkGLcall("glDisable(GL_NORMALIZE);");
3197         }
3198         break;
3199
3200     case WINED3DRS_POINTSIZE                 :
3201         tmpvalue.d = Value;
3202         TRACE("Set point size to %f\n", tmpvalue.f);
3203         glPointSize(tmpvalue.f);
3204         checkGLcall("glPointSize(...);");
3205         break;
3206
3207     case WINED3DRS_POINTSIZE_MIN             :
3208         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3209           tmpvalue.d = Value;
3210           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3211           checkGLcall("glPointParameterfEXT(...);");
3212         } else {
3213           FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3214         }
3215         break;
3216
3217     case WINED3DRS_POINTSIZE_MAX             :
3218         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3219           tmpvalue.d = Value;
3220           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3221           checkGLcall("glPointParameterfEXT(...);");
3222         } else {
3223           FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3224         }
3225         break;
3226
3227     case WINED3DRS_POINTSCALE_A              :
3228     case WINED3DRS_POINTSCALE_B              :
3229     case WINED3DRS_POINTSCALE_C              :
3230     case WINED3DRS_POINTSCALEENABLE          :
3231         {
3232             /* If enabled, supply the parameters, otherwise fall back to defaults */
3233             if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3234                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3235                 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3236                 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3237                 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3238
3239                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3240                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3241                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3242                 } else {
3243                   TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3244                 }
3245             } else {
3246                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3247                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3248                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3249                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3250                 } else {
3251                   TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3252                 }
3253             }
3254             break;
3255         }
3256
3257     case WINED3DRS_COLORWRITEENABLE          :
3258       {
3259         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3260               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
3261               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3262               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
3263               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3264         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE,
3265                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3266                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
3267                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3268         checkGLcall("glColorMask(...)");
3269       }
3270       break;
3271
3272     case WINED3DRS_LOCALVIEWER               :
3273       {
3274         GLint state = (Value) ? 1 : 0;
3275         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3276         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3277       }
3278       break;
3279
3280     case WINED3DRS_LASTPIXEL                 :
3281       {
3282         if (Value) {
3283           TRACE("Last Pixel Drawing Enabled\n");
3284         } else {
3285           FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3286         }
3287       }
3288       break;
3289
3290     case WINED3DRS_SOFTWAREVERTEXPROCESSING  :
3291       {
3292         if (Value) {
3293           TRACE("Software Processing Enabled\n");
3294         } else {
3295           TRACE("Software Processing Disabled\n");
3296         }
3297       }
3298       break;
3299
3300       /** not supported */
3301     case WINED3DRS_ZVISIBLE                  :
3302       {
3303         LEAVE_GL();
3304         return D3DERR_INVALIDCALL;
3305       }
3306
3307         /* Unhandled yet...! */
3308     case WINED3DRS_EDGEANTIALIAS             :
3309     case WINED3DRS_WRAP0                     :
3310     case WINED3DRS_WRAP1                     :
3311     case WINED3DRS_WRAP2                     :
3312     case WINED3DRS_WRAP3                     :
3313     case WINED3DRS_WRAP4                     :
3314     case WINED3DRS_WRAP5                     :
3315     case WINED3DRS_WRAP6                     :
3316     case WINED3DRS_WRAP7                     :
3317     /**
3318     http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3319     http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3320     http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3321     Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3322     http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3323
3324     so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3325     */
3326     TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3327     break;
3328     case WINED3DRS_POINTSPRITEENABLE         :
3329     case WINED3DRS_MULTISAMPLEANTIALIAS      :
3330     case WINED3DRS_MULTISAMPLEMASK           :
3331     case WINED3DRS_PATCHEDGESTYLE            :
3332     case WINED3DRS_PATCHSEGMENTS             :
3333     case WINED3DRS_DEBUGMONITORTOKEN         :
3334     case WINED3DRS_POSITIONORDER             :
3335     case WINED3DRS_NORMALORDER               :
3336         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3337         FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3338         break;
3339     default:
3340         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3341     }
3342
3343     LEAVE_GL();
3344
3345     return D3D_OK;
3346 }
3347
3348 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3349     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3350     TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3351     *pValue = This->stateBlock->renderState[State];
3352     return D3D_OK;
3353 }
3354
3355 /*****
3356  * Get / Set Sampler States
3357  * TODO: Verify against dx9 definitions
3358  *****/
3359
3360 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3361     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3362     /**
3363     * SetSampler is designed to allow for more than the standard up to 8 textures
3364     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
3365     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3366     *
3367     * http://developer.nvidia.com/object/General_FAQ.html#t6
3368     *
3369     * There are two new settings for GForce
3370     * the sampler one:
3371     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3372     * and the texture one:
3373     * GL_MAX_TEXTURE_COORDS_ARB.
3374     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3375      ******************/
3376     /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3377     TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3378
3379     if(Sampler >  GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3380          FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3381         return D3DERR_INVALIDCALL;
3382     }
3383     TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3384     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
3385
3386     /* Handle recording of state blocks */
3387     if (This->isRecordingState) {
3388         TRACE("Recording... not performing anything\n");
3389         return D3D_OK;
3390     }
3391
3392     return D3D_OK;
3393 }
3394
3395 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3396     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3397     /** TODO: check that sampler is in  range **/
3398     *Value = This->updateStateBlock->samplerState[Sampler][Type];
3399     TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3400
3401     return D3D_OK;
3402 }
3403
3404 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3405     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3406     ENTER_GL();
3407
3408     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3409     TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3410     glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3411     LEAVE_GL();
3412
3413     return D3D_OK;
3414 }
3415
3416 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3417     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3418     GLint scissorBox[4];
3419
3420     ENTER_GL();
3421     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3422     glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3423     pRect->left = scissorBox[1];
3424     pRect->top = scissorBox[2];
3425     pRect->right = scissorBox[1] + scissorBox[3];
3426     pRect->bottom = scissorBox[2] + scissorBox[4];
3427     TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3428     LEAVE_GL();
3429     return D3D_OK;
3430 }
3431
3432 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3433     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3434
3435     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3436
3437     /* TODO: what about recording stateblocks? */
3438     if (NULL != pDecl) {
3439         IWineD3DVertexDeclaration_AddRef(pDecl);
3440     }
3441     if (NULL != This->updateStateBlock->vertexDecl) {
3442       IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3443     }
3444     This->updateStateBlock->vertexDecl = pDecl;
3445     This->updateStateBlock->changed.vertexDecl = TRUE;
3446     This->updateStateBlock->set.vertexDecl = TRUE;
3447     return D3D_OK;
3448 }
3449
3450 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3451     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3452
3453     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3454
3455     *ppDecl = This->updateStateBlock->vertexDecl;
3456     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3457     return D3D_OK;
3458 }
3459
3460 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3461     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3462     IWineD3DVertexShader *oldShader = This->updateStateBlock->vertexShader;
3463
3464     This->updateStateBlock->vertexShader = pShader;
3465     This->updateStateBlock->changed.vertexShader = TRUE;
3466     This->updateStateBlock->set.vertexShader = TRUE;
3467
3468     if (This->isRecordingState) {
3469         TRACE("Recording... not performing anything\n");
3470         return D3D_OK;
3471     }
3472
3473     if (pShader != NULL) {
3474         IUnknown *newVertexShaderParent;
3475         /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
3476         TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3477         IWineD3DVertexShader_GetParent(pShader, &newVertexShaderParent);
3478     } else {
3479         TRACE("Clear down the shader\n");
3480     }
3481     if (oldShader != NULL) {
3482         IUnknown *oldVertexShaderParent;
3483         IWineD3DVertexShader_GetParent(oldShader, &oldVertexShaderParent);
3484         IUnknown_Release(oldVertexShaderParent);
3485         IUnknown_Release(oldVertexShaderParent);
3486     }
3487     /**
3488      * TODO: merge HAL shaders context switching from prototype
3489      */
3490     return D3D_OK;
3491 }
3492
3493 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3494     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3495
3496     if (NULL == ppShader) {
3497         return D3DERR_INVALIDCALL;
3498     }
3499     *ppShader = This->stateBlock->vertexShader;
3500     if( NULL != *ppShader)
3501         IWineD3DVertexShader_AddRef(*ppShader);
3502
3503     TRACE("(%p) : returning %p\n", This, *ppShader);
3504     return D3D_OK;
3505 }
3506
3507 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3508 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3509 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3510     return D3DERR_INVALIDCALL; \
3511 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3512
3513 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3514 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3515 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3516     return D3DERR_INVALIDCALL; \
3517 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3518 This->updateStateBlock->changed.vertexShader = TRUE; \
3519 This->updateStateBlock->set.vertexShader = TRUE;
3520
3521 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL  *pConstantData, UINT BoolCount){
3522     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3523     static BOOL showFixmes = TRUE;
3524     SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3525 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3526     memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTB, BoolCount);
3527 #endif
3528     /* clean out the other constants? */
3529     if(showFixmes || TRUE) {
3530         FIXME("(%p) : stub\n", This);
3531         showFixmes = FALSE;
3532     }
3533     return D3D_OK;
3534 }
3535
3536 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3537     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3538     static BOOL showFixmes = TRUE;
3539 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3540     for (i = 0; i < BoolCount; i++ ) {
3541         if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTB) {
3542             /* the constant for this register isn't a boolean */
3543             return D3DERR_INVALIDCALL;
3544         }
3545     }
3546 #endif
3547     GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3548     if(showFixmes || TRUE) {
3549         FIXME("(%p) : stub\n", This);
3550         showFixmes = FALSE;
3551     }
3552     return D3D_OK;
3553 }
3554
3555 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3556     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3557     static BOOL showFixmes = TRUE;
3558 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3559     memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTI, Vector4iCount);
3560 #endif
3561     SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3562     /* clean out the other constants? */
3563     if(showFixmes || TRUE) {
3564         FIXME("(%p) : stub\n", This);
3565         showFixmes = FALSE;
3566     }
3567     return D3D_OK;
3568 }
3569
3570 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int         *pConstantData, UINT Vector4iCount){
3571     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3572     static BOOL showFixmes = TRUE;
3573 #if 0 /* TODO: a bitmap to say which constant type we should load */
3574     for (i = 0; i < Vector4iCount; i++ ) {
3575         if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTI) {
3576             /* the constant for this register isn't a boolean */
3577             return D3DERR_INVALIDCALL;
3578         }
3579     }
3580 #endif
3581     GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3582     if(showFixmes || TRUE) {
3583         FIXME("(%p) : stub\n", This);
3584         showFixmes = FALSE;
3585     }
3586     return D3D_OK;
3587 }
3588
3589 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3590     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3591     static BOOL showFixmes = TRUE;
3592 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3593     memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTF, Vector4fCount);
3594 #endif
3595     SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3596     /* clean out the other constants? */
3597     if(showFixmes) {
3598         TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3599         showFixmes = FALSE;
3600     }
3601     return D3D_OK;
3602 }
3603
3604 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float       *pConstantData, UINT Vector4fCount){
3605     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3606     static BOOL showFixmes = TRUE;
3607 #if 0 /* TODO: a bitmap to say which constant type we should load */
3608     for (i = 0; i < Vector4fCount; i++ ) {
3609         if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTF) {
3610             /* the constant for this register isn't a boolean */
3611             return D3DERR_INVALIDCALL;
3612         }
3613     }
3614 #endif
3615     GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3616     if(showFixmes) {
3617         TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3618         showFixmes = FALSE;
3619     }
3620     return D3D_OK;
3621 }
3622
3623 #undef SET_SHADER_CONSTANT
3624 #undef GET_SHADER_CONSTANT
3625
3626
3627 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader  *pShader) {
3628     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3629     TRACE("(%p) : stub\n", This);
3630     return D3D_OK;
3631 }
3632
3633 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3634     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3635     TRACE("(%p) : stub\n", This);
3636     return D3D_OK;
3637 }
3638
3639
3640 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL   *pConstantData, UINT BoolCount) {
3641     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3642     TRACE("(%p) : stub\n", This);
3643     return D3D_OK;
3644 }
3645
3646 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL         *pConstantData, UINT BoolCount) {
3647     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3648     TRACE("(%p) : stub\n", This);
3649     return D3D_OK;
3650 }
3651
3652 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int    *pConstantData, UINT Vector4iCount) {
3653     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3654     TRACE("(%p) : stub\n", This);
3655     return D3D_OK;
3656 }
3657
3658 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int          *pConstantData, UINT Vector4iCount) {
3659     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3660     TRACE("(%p) : stub\n", This);
3661     return D3D_OK;
3662 }
3663
3664 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float  *pConstantData, UINT Vector4fCount) {
3665     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3666     TRACE("(%p) : stub\n", This);
3667     return D3D_OK;
3668 }
3669
3670 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float        *pConstantData, UINT Vector4fCount) {
3671     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3672     TRACE("(%p) : stub\n", This);
3673     return D3D_OK;
3674 }
3675
3676 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3677     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3678     FIXME("(%p) : stub\n", This);
3679     return D3D_OK;
3680 }
3681
3682 /*****
3683  * Apply / Get / Set Texture Stage States
3684  * TODO: Verify against dx9 definitions
3685  *****/
3686
3687 /* 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 */
3688 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
3689     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3690     DWORD Value = This->updateStateBlock->textureState[Stage][Type];
3691     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3692
3693     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3694
3695     /* Check that the stage is within limits  */
3696     if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3697         TRACE("Attempt to access invalid texture rejected\n");
3698         return;
3699     }
3700
3701     ENTER_GL();
3702
3703     switch (Type) {
3704     case WINED3DTSS_ALPHAOP               :
3705     case WINED3DTSS_COLOROP               :
3706         {
3707
3708             if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3709                 /* TODO: Disable by making this and all later levels disabled */
3710                 glDisable(GL_TEXTURE_1D);
3711                 checkGLcall("Disable GL_TEXTURE_1D");
3712                 glDisable(GL_TEXTURE_2D);
3713                 checkGLcall("Disable GL_TEXTURE_2D");
3714                 glDisable(GL_TEXTURE_3D);
3715                 checkGLcall("Disable GL_TEXTURE_3D");
3716                 break; /* Don't bother setting the texture operations */
3717             } else {
3718                 /* Enable only the appropriate texture dimension */
3719                 if (Type == WINED3DTSS_COLOROP) {
3720                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3721                         glEnable(GL_TEXTURE_1D);
3722                         checkGLcall("Enable GL_TEXTURE_1D");
3723                     } else {
3724                         glDisable(GL_TEXTURE_1D);
3725                         checkGLcall("Disable GL_TEXTURE_1D");
3726                     }
3727                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3728                       if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3729                         glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3730                         checkGLcall("Enable GL_TEXTURE_2D");
3731                       } else {
3732                         glEnable(GL_TEXTURE_2D);
3733                         checkGLcall("Enable GL_TEXTURE_2D");
3734                       }
3735                     } else {
3736                         glDisable(GL_TEXTURE_2D);
3737                         checkGLcall("Disable GL_TEXTURE_2D");
3738                     }
3739                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3740                         glEnable(GL_TEXTURE_3D);
3741                         checkGLcall("Enable GL_TEXTURE_3D");
3742                     } else {
3743                         glDisable(GL_TEXTURE_3D);
3744                         checkGLcall("Disable GL_TEXTURE_3D");
3745                     }
3746                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3747                         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3748                         checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3749                     } else {
3750                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3751                         checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3752                     }
3753                 }
3754             }
3755             /* Drop through... (Except disable case) */
3756         case WINED3DTSS_COLORARG0             :
3757         case WINED3DTSS_COLORARG1             :
3758         case WINED3DTSS_COLORARG2             :
3759         case WINED3DTSS_ALPHAARG0             :
3760         case WINED3DTSS_ALPHAARG1             :
3761         case WINED3DTSS_ALPHAARG2             :
3762             {
3763                 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3764                                    Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3765                 if (isAlphaArg) {
3766                     set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3767                                This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3768                                This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3769                                This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3770                 } else {
3771                     set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3772                                This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3773                                This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3774                                This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3775                 }
3776             }
3777             break;
3778         }
3779
3780     case WINED3DTSS_ADDRESSW              :
3781         {
3782             GLint wrapParm = GL_REPEAT;
3783
3784             switch (Value) {
3785             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
3786             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;
3787             case D3DTADDRESS_BORDER:
3788               {
3789                 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3790                   wrapParm = GL_CLAMP_TO_BORDER_ARB;
3791                 } else {
3792                   /* FIXME: Not right, but better */
3793                   FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3794                   wrapParm = GL_REPEAT;
3795                 }
3796               }
3797               break;
3798             case D3DTADDRESS_MIRROR:
3799               {
3800                 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3801                   wrapParm = GL_MIRRORED_REPEAT_ARB;
3802                 } else {
3803                   /* Unsupported in OpenGL pre-1.4 */
3804                   FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3805                   wrapParm = GL_REPEAT;
3806                 }
3807               }
3808               break;
3809             case D3DTADDRESS_MIRRORONCE:
3810               {
3811                 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3812                   wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3813                 } else {
3814                   FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3815                   wrapParm = GL_REPEAT;
3816                 }
3817               }
3818               break;
3819
3820             default:
3821                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3822                 wrapParm = GL_REPEAT;
3823             }
3824
3825             TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3826             glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3827             checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3828         }
3829         break;
3830
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->textureState[Stage][Type]         = Value;
4029
4030     return D3D_OK;
4031 }
4032
4033 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4034     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4035     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4036     *pValue = This->updateStateBlock->textureState[Stage][Type];
4037     return D3D_OK;
4038 }
4039
4040 /*****
4041  * Get / Set Texture
4042  *****/
4043 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4044
4045     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4046     IWineD3DBaseTexture   *oldTexture;
4047
4048     oldTexture = This->updateStateBlock->textures[Stage];
4049     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4050
4051 #if 0 /* TODO: check so vertex textures */
4052     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4053         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4054         return D3D_OK;
4055     }
4056 #endif
4057
4058     /* Reject invalid texture units */
4059     if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4060         WARN("Attempt to access invalid texture rejected\n");
4061         return D3DERR_INVALIDCALL;
4062     }
4063
4064     oldTexture = This->updateStateBlock->textures[Stage];
4065     TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4066     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4067
4068     This->updateStateBlock->set.textures[Stage]     = TRUE;
4069     This->updateStateBlock->changed.textures[Stage] = TRUE;
4070     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4071     This->updateStateBlock->textures[Stage]         = pTexture;
4072
4073     /* Handle recording of state blocks */
4074     if (This->isRecordingState) {
4075         TRACE("Recording... not performing anything\n");
4076         return D3D_OK;
4077     }
4078
4079     /** NOTE: MSDN says that setTexture increases the reference count,
4080     * and the the application nust set the texture back to null (or have a leaky application),
4081     * This means we should pass the refcount upto the parent
4082      *******************************/
4083     if (NULL != This->updateStateBlock->textures[Stage]) {
4084         IUnknown *textureParent;
4085         IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4086         /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
4087     }
4088
4089     if (NULL != oldTexture) {
4090         IUnknown *textureParent;
4091         IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4092         IUnknown_Release(textureParent);
4093         IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4094         oldTexture = NULL;
4095     }
4096
4097     return D3D_OK;
4098 }
4099
4100 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4101     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4102     TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */) \n", This, Stage, ppTexture);
4103
4104     /* Reject invalid texture units */
4105     if (Stage >= GL_LIMITS(textures)) {
4106         TRACE("Attempt to access invalid texture rejected\n");
4107         return D3DERR_INVALIDCALL;
4108     }
4109     *ppTexture=This->updateStateBlock->textures[Stage];
4110     if (*ppTexture)
4111         IWineD3DBaseTexture_AddRef(*ppTexture);
4112     else
4113         return D3DERR_INVALIDCALL;
4114     return D3D_OK;
4115 }
4116
4117 /*****
4118  * Get Back Buffer
4119  *****/
4120 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4121                                                 IWineD3DSurface **ppBackBuffer) {
4122     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4123     IWineD3DSwapChain *swapChain;
4124     HRESULT hr;
4125
4126     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4127
4128     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4129     if (hr == D3D_OK) {
4130         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4131             IWineD3DSwapChain_Release(swapChain);
4132     } else {
4133         *ppBackBuffer = NULL;
4134     }
4135     return hr;
4136 }
4137
4138 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4139     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4140     WARN("(%p) : stub, calling idirect3d for now\n", This);
4141     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4142 }
4143
4144 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4145     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4146     IWineD3DSwapChain *swapChain;
4147     HRESULT hr;
4148
4149     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4150     if (hr == D3D_OK) {
4151         hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4152         IWineD3DSwapChain_Release(swapChain);
4153     } else {
4154         FIXME("(%p) Error getting display mode\n", This);
4155     }
4156     return hr;
4157 }
4158 /*****
4159  * Stateblock related functions
4160  *****/
4161
4162 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4163     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4164     IWineD3DStateBlockImpl *object;
4165     TRACE("(%p)", This);
4166     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4167     if (NULL == object ) {
4168         FIXME("(%p)Error allocating memory for stateblock\n", This);
4169         return E_OUTOFMEMORY;
4170     }
4171     TRACE("(%p) creted object %p\n", This, object);
4172     object->wineD3DDevice= This;
4173     /** FIXME: object->parent       = parent; **/
4174     object->parent       = NULL;
4175     object->blockType    = WINED3DSBT_ALL;
4176     object->ref          = 1;
4177     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4178
4179     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4180     This->updateStateBlock = object;
4181     This->isRecordingState = TRUE;
4182
4183     TRACE("(%p) recording stateblock %p\n",This , object);
4184     return D3D_OK;
4185 }
4186
4187 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4188     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4189
4190     if (!This->isRecordingState) {
4191         FIXME("(%p) not recording! returning error\n", This);
4192         *ppStateBlock = NULL;
4193         return D3DERR_INVALIDCALL;
4194     }
4195
4196     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4197     This->isRecordingState = FALSE;
4198     This->updateStateBlock = This->stateBlock;
4199     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4200     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4201     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4202     return D3D_OK;
4203 }
4204
4205 /*****
4206  * Scene related functions
4207  *****/
4208 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4209     /* At the moment we have no need for any functionality at the beginning
4210        of a scene                                                          */
4211     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4212     TRACE("(%p) : stub\n", This);
4213     return D3D_OK;
4214 }
4215
4216 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4217     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4218     TRACE("(%p)\n", This);
4219     ENTER_GL();
4220     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4221     glFlush();
4222     checkGLcall("glFlush");
4223
4224     TRACE("End Scene\n");
4225     if(This->renderTarget != NULL) {
4226
4227         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4228         IUnknown *targetContainer = NULL;
4229         if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4230             || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4231             TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4232             /** always dirtify for now. we must find a better way to see that surface have been modified
4233             (Modifications should will only occur via draw-primitive, but we do need better locking
4234             switching to render-to-texture should remove the overhead though.
4235             */
4236             IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4237             IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4238             IWineD3DSurface_PreLoad(This->renderTarget);
4239             IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4240             IUnknown_Release(targetContainer);
4241         }
4242     }
4243     This->sceneEnded = TRUE;
4244     LEAVE_GL();
4245     return D3D_OK;
4246 }
4247
4248 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4249                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4250                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4251     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4252     IWineD3DSwapChain *swapChain = NULL;
4253     int i;
4254     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4255
4256     TRACE("(%p) Presenting the frame\n", This);
4257
4258     for(i = 0 ; i < swapchains ; i ++) {
4259
4260         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4261         TRACE("presentinng chain %d, %p\n", i, swapChain);
4262         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4263         IWineD3DSwapChain_Release(swapChain);
4264     }
4265
4266     return D3D_OK;
4267 }
4268
4269 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4270                                         DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4271     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4272
4273     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4274       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4275       when the depth-buffer format does not contain stencil buffer information, this method fails. */
4276     GLbitfield     glMask = 0;
4277     GLboolean      old_ztest;
4278     GLfloat        old_z_clear_value;
4279     GLint          old_stencil_clear_value;
4280     GLfloat        old_color_clear_value[4];
4281     unsigned int   i;
4282     CONST D3DRECT* curRect;
4283
4284     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4285           Count, pRects, Flags, Z, Stencil);
4286
4287     ENTER_GL();
4288
4289     glEnable(GL_SCISSOR_TEST);
4290     checkGLcall("glEnable GL_SCISSOR_TEST");
4291
4292     if (Count > 0 && pRects) {
4293         curRect = pRects;
4294     } else {
4295         curRect = NULL;
4296     }
4297
4298     /* Only set the values up once, as they are not changing */
4299     if (Flags & D3DCLEAR_STENCIL) {
4300         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4301         glClearStencil(Stencil);
4302         checkGLcall("glClearStencil");
4303         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4304         glStencilMask(0xFFFFFFFF);
4305     }
4306
4307     if (Flags & D3DCLEAR_ZBUFFER) {
4308         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4309         glDepthMask(GL_TRUE);
4310         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4311         glClearDepth(Z);
4312         checkGLcall("glClearDepth");
4313         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4314     }
4315
4316     if (Flags & D3DCLEAR_TARGET) {
4317         TRACE("Clearing screen with glClear to color %lx\n", Color);
4318         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4319         glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4320                      ((Color >>  8) & 0xFF) / 255.0f,
4321                      ((Color >>  0) & 0xFF) / 255.0f,
4322                      ((Color >> 24) & 0xFF) / 255.0f);
4323         checkGLcall("glClearColor");
4324
4325         /* Clear ALL colors! */
4326         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4327         glMask = glMask | GL_COLOR_BUFFER_BIT;
4328     }
4329
4330     /* Now process each rect in turn */
4331     for (i = 0; i < Count || i == 0; i++) {
4332
4333         if (curRect) {
4334             /* Note gl uses lower left, width/height */
4335             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4336                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4337                   curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4338                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4339             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4340                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4341             checkGLcall("glScissor");
4342         } else {
4343             glScissor(This->stateBlock->viewport.X,
4344                       (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - 
4345                       (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4346                       This->stateBlock->viewport.Width,
4347                       This->stateBlock->viewport.Height);
4348             checkGLcall("glScissor");
4349         }
4350
4351         /* Clear the selected rectangle (or full screen) */
4352         glClear(glMask);
4353         checkGLcall("glClear");
4354
4355         /* Step to the next rectangle */
4356         if (curRect) curRect = curRect + sizeof(D3DRECT);
4357     }
4358
4359     /* Restore the old values (why..?) */
4360     if (Flags & D3DCLEAR_STENCIL) {
4361         glClearStencil(old_stencil_clear_value);
4362         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4363     }
4364     if (Flags & D3DCLEAR_ZBUFFER) {
4365         glDepthMask(old_ztest);
4366         glClearDepth(old_z_clear_value);
4367     }
4368     if (Flags & D3DCLEAR_TARGET) {
4369         glClearColor(old_color_clear_value[0],
4370                      old_color_clear_value[1],
4371                      old_color_clear_value[2],
4372                      old_color_clear_value[3]);
4373         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4374                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4375                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4376                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4377     }
4378
4379     glDisable(GL_SCISSOR_TEST);
4380     checkGLcall("glDisable");
4381     LEAVE_GL();
4382
4383     return D3D_OK;
4384 }
4385
4386 /*****
4387  * Drawing functions
4388  *****/
4389 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4390                                                 UINT PrimitiveCount) {
4391
4392     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4393     This->stateBlock->streamIsUP = FALSE;
4394
4395     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4396                                debug_d3dprimitivetype(PrimitiveType),
4397                                StartVertex, PrimitiveCount);
4398     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4399                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4400
4401
4402     return D3D_OK;
4403 }
4404
4405 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4406 HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4407                                                            D3DPRIMITIVETYPE PrimitiveType,
4408                                                            INT baseVIndex, UINT minIndex,
4409                                                            UINT NumVertices, UINT startIndex, UINT primCount) {
4410
4411     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4412     UINT                 idxStride = 2;
4413     IWineD3DIndexBuffer *pIB;
4414     D3DINDEXBUFFER_DESC  IdxBufDsc;
4415
4416     pIB = This->stateBlock->pIndexData;
4417     This->stateBlock->streamIsUP = FALSE;
4418
4419     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4420           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4421           minIndex, NumVertices, startIndex, baseVIndex, primCount);
4422
4423     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4424     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4425         idxStride = 2;
4426     } else {
4427         idxStride = 4;
4428     }
4429
4430     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4431                    idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4432
4433     return D3D_OK;
4434 }
4435
4436 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4437                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4438                                                     UINT VertexStreamZeroStride) {
4439     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4440
4441     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4442              debug_d3dprimitivetype(PrimitiveType),
4443              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4444
4445     if (This->stateBlock->streamSource[0] != NULL) {
4446         IUnknown *vertexBufferParent;
4447         IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4448         IUnknown_Release(vertexBufferParent);
4449         IUnknown_Release(vertexBufferParent);
4450     }
4451
4452     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4453     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4454     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4455     This->stateBlock->streamIsUP = TRUE;
4456
4457     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4458                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4459     /* stream zero settings set to null at end, as per the msdn
4460             http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4461     */
4462     This->stateBlock->streamStride[0] = 0;
4463     This->stateBlock->streamSource[0] = NULL;
4464
4465     /*stream zero settings set to null at end, as per the msdn */
4466     return D3D_OK;
4467 }
4468
4469 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4470                                                              UINT MinVertexIndex, UINT NumVertices,
4471                                                              UINT PrimitiveCount, CONST void* pIndexData,
4472                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4473                                                              UINT VertexStreamZeroStride) {
4474     int                 idxStride;
4475     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4476
4477     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4478              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4479              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4480              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4481
4482     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4483         idxStride = 2;
4484     } else {
4485         idxStride = 4;
4486     }
4487
4488     if (This->stateBlock->streamSource[0] != NULL) {
4489         IUnknown *vertexBufferParent;
4490         IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4491         This->stateBlock->streamSource[0] = NULL;
4492         IUnknown_Release(vertexBufferParent);
4493         IUnknown_Release(vertexBufferParent);
4494     }
4495
4496     if (This->stateBlock->pIndexData) {
4497         IUnknown *indexBufferParent;
4498         IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4499         This->stateBlock->pIndexData = NULL;
4500         IUnknown_Release(indexBufferParent);
4501         IUnknown_Release(indexBufferParent);
4502     }
4503
4504     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4505     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4506     This->stateBlock->streamIsUP = TRUE;
4507     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4508
4509     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4510     /* stream zero settings set to null at end as per the msdn
4511     http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4512     */
4513
4514     /* stream zero settings set to null at end as per the msdn */
4515     This->stateBlock->streamSource[0] = NULL;
4516     This->stateBlock->streamStride[0] = 0;
4517
4518     return D3D_OK;
4519 }
4520
4521  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4522 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4523     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4524     D3DRESOURCETYPE sourceType;
4525     D3DRESOURCETYPE destinationType;
4526     IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4527     IWineD3DTextureImpl *pSrcTexture  = (IWineD3DTextureImpl *)pSourceTexture;
4528     int i;
4529
4530     sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4531     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4532     if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4533         FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4534         return D3DERR_INVALIDCALL;
4535     }
4536     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4537
4538     /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4539         repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4540         think about moving the code into texture, and adding a member to base texture to occomplish this **/
4541
4542     /* Make sure that the destination texture is loaded */
4543     IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4544     TRACE("Loading source texture\n");
4545
4546     if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4547         FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4548                pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4549     }
4550
4551     if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4552         ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4553
4554         FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4555         return D3DERR_INVALIDCALL;
4556     }
4557     /** TODO: check that both textures have the same number of levels  **/
4558 #if 0
4559     if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4560             return D3DERR_INVALIDCALL;
4561 #endif
4562     /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4563     for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4564         IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4565     }
4566
4567     return D3D_OK;
4568 }
4569
4570 HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4571                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4572                                                 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4573     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4574
4575     TRACE("(%p) : stub\n", This);
4576     return D3D_OK;
4577 }
4578 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4579     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4580
4581     TRACE("(%p) : stub\n", This);
4582     return D3D_OK;
4583 }
4584
4585 HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4586     IWineD3DSwapChain *swapChain;
4587     HRESULT hr;
4588     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4589     if(hr == D3D_OK) {
4590         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4591                 IWineD3DSwapChain_Release(swapChain);
4592     }
4593     return hr;
4594 }
4595
4596 HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4597     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4598     /* return a sensible default */
4599     *pNumPasses = 1;
4600     /* TODO: If the window is minimized then validate device shold return something other than d3d_ok */
4601     FIXME("(%p) : stub\n", This);
4602     return D3D_OK;
4603 }
4604
4605 HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4606     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4607     int j;
4608     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4609     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4610         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4611         return D3DERR_INVALIDCALL;
4612     }
4613     for (j = 0; j < 256; ++j) {
4614         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
4615         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4616         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
4617         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4618     }
4619     TRACE("(%p) : returning\n", This);
4620     return D3D_OK;
4621 }
4622
4623 HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4624     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4625     int j;
4626     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4627     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4628         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4629         return D3DERR_INVALIDCALL;
4630     }
4631     for (j = 0; j < 256; ++j) {
4632         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
4633         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4634         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
4635         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4636     }
4637     TRACE("(%p) : returning\n", This);
4638     return D3D_OK;
4639 }
4640
4641 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4642     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4643     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4644     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4645         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4646         return D3DERR_INVALIDCALL;
4647     }
4648     /*TODO: stateblocks */
4649     This->currentPalette = PaletteNumber;
4650     TRACE("(%p) : returning\n", This);
4651     return D3D_OK;
4652 }
4653
4654 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4655     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656     if (PaletteNumber == NULL) {
4657         WARN("(%p) : returning Invalid Call\n", This);
4658         return D3DERR_INVALIDCALL;
4659     }
4660     /*TODO: stateblocks */
4661     *PaletteNumber = This->currentPalette;
4662     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
4663     return D3D_OK;
4664 }
4665
4666 HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4667     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4668     static BOOL showFixmes = TRUE;
4669     if (showFixmes) {
4670         FIXME("(%p) : stub\n", This);
4671         showFixmes = FALSE;
4672     }
4673
4674     This->updateStateBlock->softwareVertexProcessing = bSoftware;
4675     return D3D_OK;
4676 }
4677
4678
4679 BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4680     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4681     static BOOL showFixmes = TRUE;
4682     if (showFixmes) {
4683         FIXME("(%p) : stub\n", This);
4684         showFixmes = FALSE;
4685     }
4686     return This->updateStateBlock->softwareVertexProcessing;
4687 }
4688
4689
4690 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4691     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4692
4693     pRasterStatus->InVBlank = TRUE;
4694     pRasterStatus->ScanLine = 0;
4695     FIXME("(%p) : stub\n", This);
4696     return D3D_OK;
4697 }
4698
4699
4700 HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4701     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4702     static BOOL showfixmes = TRUE;
4703     if(nSegments != 0.0f) {
4704         if( showfixmes) {
4705             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4706             showfixmes = FALSE;
4707         }
4708     }
4709     return D3D_OK;
4710 }
4711
4712 float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4713     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4714     static BOOL showfixmes = TRUE;
4715     if( showfixmes) {
4716         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4717         showfixmes = FALSE;
4718     }
4719     return 0.0f;
4720 }
4721
4722
4723 HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4724     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
4725     /** TODO: remove casts to IWineD3DSurfaceImpl
4726      *       NOTE: move code to surface to accomplish this
4727       ****************************************/
4728     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
4729     int srcWidth, srcHeight;
4730     unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4731     WINED3DFORMAT destFormat, srcFormat;
4732     UINT destSize;
4733     int destLeft, destTop;
4734     D3DPOOL     srcPool, destPool;
4735     int offset    = 0;
4736     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4737     glDescriptor *glDescription = NULL;
4738     GLenum textureDimensions = GL_TEXTURE_2D;
4739     IWineD3DBaseTexture *baseTexture;
4740
4741     WINED3DSURFACE_DESC  winedesc;
4742
4743     memset(&winedesc, 0, sizeof(winedesc));
4744     winedesc.Width  = &srcSurfaceWidth;
4745     winedesc.Height = &srcSurfaceHeight;
4746     winedesc.Pool   = &srcPool;
4747     winedesc.Format = &srcFormat;
4748
4749     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4750
4751     winedesc.Width  = &destSurfaceWidth;
4752     winedesc.Height = &destSurfaceHeight;
4753     winedesc.Pool   = &destPool;
4754     winedesc.Format = &destFormat;
4755     winedesc.Size   = &destSize;
4756
4757     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4758
4759     if(srcPool != D3DPOOL_SYSTEMMEM  || destPool != D3DPOOL_DEFAULT){
4760         FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4761         return D3DERR_INVALIDCALL;
4762     }
4763     /* TODO:  change this to use bindTexture */
4764     /* Make sure the surface is loaded and upto date */
4765     IWineD3DSurface_PreLoad(pDestinationSurface);
4766
4767     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4768
4769     ENTER_GL();
4770
4771     /* this needs to be done in lines if the sourceRect != the sourceWidth */
4772     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
4773     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
4774     destLeft   = pDestPoint  ? pDestPoint->x : 0;
4775     destTop    = pDestPoint  ? pDestPoint->y : 0;
4776
4777
4778     /* This function doesn't support compressed textures
4779     the pitch is just bytesPerPixel * width */
4780
4781     if(srcWidth != srcSurfaceWidth  || (pSourceRect != NULL && pSourceRect->left != 0) ){
4782         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4783         offset   += pSourceRect->left * pSrcSurface->bytesPerPixel;
4784         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4785     }
4786     /* TODO DXT formats */
4787
4788     if(pSourceRect != NULL && pSourceRect->top != 0){
4789        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4790     }
4791     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4792     ,This
4793     ,glDescription->level
4794     ,destLeft
4795     ,destTop
4796     ,srcWidth
4797     ,srcHeight
4798     ,glDescription->glFormat
4799     ,glDescription->glType
4800     ,IWineD3DSurface_GetData(pSourceSurface)
4801     );
4802
4803     /* Sanity check */
4804     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4805     /* need to lock the surface to get the data */
4806        FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4807     }
4808     /* TODO: Cube and volume support */
4809     if(rowoffset != 0){
4810         /* not a whole row so we have to do it a line at a time */
4811         int j;
4812         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4813         unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4814
4815         for(j = destTop ; j < (srcHeight + destTop) ; j++){
4816
4817                 glTexSubImage2D(glDescription->target
4818                     ,glDescription->level
4819                     ,destLeft
4820                     ,j
4821                     ,srcWidth
4822                     ,1
4823                     ,glDescription->glFormat
4824                     ,glDescription->glType
4825                     ,data/* could be quicker using */
4826                 );
4827             data += rowoffset;
4828         }
4829
4830     } else { /* Full width, so just write out the whole texture */
4831
4832         if (WINED3DFMT_DXT1 == destFormat ||
4833             WINED3DFMT_DXT3 == destFormat ||
4834             WINED3DFMT_DXT5 == destFormat) {
4835             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4836                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4837                     /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4838                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
4839                 } if (destFormat != srcFormat) {
4840                     FIXME("Updating mixed format compressed texture is not curretly support\n");
4841                 } else {
4842                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4843                                                         glDescription->level,
4844                                                         glDescription->glFormatInternal,
4845                                                         srcWidth,
4846                                                         srcHeight,
4847                                                         0,
4848                                                         destSize,
4849                                                         IWineD3DSurface_GetData(pSourceSurface));
4850                 }
4851             } else {
4852                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4853             }
4854
4855
4856         } else {
4857             /* some applications cannot handle odd pitches returned by soft non-power2, so we have
4858                to repack the data from pow2Width/Height to expected Width,Height, this makes the
4859                data returned by GetData non-power2 width/height with hardware non-power2
4860                pow2Width/height are set to surface width height, repacking isn't needed so it
4861                doesn't matter which function gets called. */
4862             glTexSubImage2D(glDescription->target
4863                     ,glDescription->level
4864                     ,destLeft
4865                     ,destTop
4866                     ,srcWidth
4867                     ,srcHeight
4868                     ,glDescription->glFormat
4869                     ,glDescription->glType
4870                     ,IWineD3DSurface_GetData(pSourceSurface)
4871                 );
4872
4873         }
4874      }
4875     checkGLcall("glTexSubImage2D");
4876     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4877      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4878      * surface bigger than it needs to be hmm.. */
4879     if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
4880         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
4881         IWineD3DBaseTexture_Release(baseTexture);
4882     }
4883
4884     glDisable(textureDimensions); /* This needs to be managed better.... */
4885     LEAVE_GL();
4886
4887     return D3D_OK;
4888 }
4889
4890 /* Implementation details at http://developer.nvidia.com/attach/6494
4891 and
4892 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4893 hmm.. no longer supported use
4894 OpenGL evaluators or  tessellate surfaces within your application.
4895 */
4896
4897 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4898 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4899     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4900     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4901     FIXME("(%p) : Stub\n", This);
4902     return D3D_OK;
4903
4904 }
4905
4906 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4907 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4908     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4909     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4910     FIXME("(%p) : Stub\n", This);
4911     return D3D_OK;
4912 }
4913
4914 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4915     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4916     TRACE("(%p) Handle(%d)\n", This, Handle);
4917     FIXME("(%p) : Stub\n", This);
4918     return D3D_OK;
4919 }
4920
4921 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
4922     /* I couldn't find a 'really' quick way of doing this in openGl so here goes
4923     fill a surface with a block of color!  */
4924     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4925     /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
4926     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
4927     IWineD3DSwapChainImpl *container = NULL;
4928     BOOL isRenderTarget = FALSE;
4929     unsigned int width, height;
4930     unsigned int top, left;
4931     unsigned int u, v;
4932     DWORD       *data;
4933     TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
4934
4935     if (surface->resource.pool != D3DPOOL_DEFAULT) {
4936         FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
4937         return D3DERR_INVALIDCALL;
4938     }
4939
4940     /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
4941     if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
4942         if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
4943             /* TODO: make sure we set everything back to the way it was, and context management!
4944                 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4945                 vcheckGLcall("glIntegerv");
4946                 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
4947                 vcheckGLcall("glIntegerv");
4948             */
4949             TRACE("Color fill to render targets may cause some graphics issues\n");
4950             if (pSurface == container->frontBuffer) {
4951                 glDrawBuffer(GL_FRONT);
4952             } else {
4953                 glDrawBuffer(GL_BACK);
4954             }
4955         } else {
4956             if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
4957                 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
4958             } else {
4959                 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
4960             }
4961             if (container != NULL) {
4962                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4963             }
4964             /* we can use GL_STENCIL_INDEX etc...*/
4965             return D3D_OK;
4966         }
4967         if (container != NULL) {
4968             IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4969         }
4970         isRenderTarget = TRUE;
4971     }
4972     /* TODO: drawing to GL_FRONT and GL_BACK */
4973     /* TODO: see if things can be speeded up by using the correct
4974      * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
4975     if (pRect == NULL) {
4976         top    = 0;
4977         left   = 0;
4978         width  = surface->currentDesc.Width;
4979         height = surface->currentDesc.Height;
4980     } else {
4981         left   = pRect->x1;
4982         top    = pRect->y1;
4983         width  = pRect->x2 - left;
4984         height = pRect->y2 - top;
4985     }
4986
4987     data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
4988     /* Create a 'line' of color color, in the correct format for the surface */
4989     for (u = 0 ; u < width ; u ++) {
4990             data[u] = color;
4991     }
4992
4993     ENTER_GL();
4994     if (isRenderTarget == FALSE) {
4995         glDescriptor *glDesc;
4996         IWineD3DSurface_PreLoad(pSurface);
4997
4998         /* draw a block of the coloured line on the sufrace */
4999         IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5000         for (v = 0 ; v< height;v++) {
5001             glTexSubImage2D(glDesc->target
5002                             ,glDesc->level /* level */
5003                             ,left
5004                             ,top + v
5005                             ,width
5006                             ,1 /* height */
5007                             ,GL_RGBA
5008                             ,GL_UNSIGNED_BYTE
5009                             ,data
5010                             );
5011         }
5012         checkGLcall("glTexSubImage2D");
5013         /* clean up */
5014         glDisable(glDesc->target);
5015     } else {
5016         /** FIXME: Using GLClear may be faster **/
5017         glRasterPos2i(left, top);
5018         glPixelZoom((float)width ,(float)height);
5019         glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5020         checkGLcall("glDrawPixels");
5021     }
5022     HeapFree(GetProcessHeap(), 0, data);
5023     LEAVE_GL();
5024     return D3D_OK;
5025
5026 }
5027
5028 /* rendertarget and deptth stencil functions */
5029 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5030     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5031
5032     /* FIXME: Implelent RenderTargetIndex >0 */
5033     if(RenderTargetIndex > 0)
5034         FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5035
5036     *ppRenderTarget = This->renderTarget;
5037     TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5038     /* Note inc ref on returned surface */
5039     if(*ppRenderTarget != NULL)
5040         IWineD3DSurface_AddRef(*ppRenderTarget);
5041     return D3D_OK;
5042 }
5043
5044 HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5045     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5046     *ppZStencilSurface = This->depthStencilBuffer;
5047     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5048
5049     if(*ppZStencilSurface != NULL) {
5050         /* Note inc ref on returned surface */
5051         IWineD3DSurface_AddRef(*ppZStencilSurface);
5052     }
5053     return D3D_OK;
5054 }
5055
5056 /* internal static helper functions */
5057 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5058                                                 IWineD3DSurface *RenderSurface);
5059
5060 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
5061
5062 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
5063
5064 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5065     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5066     HRESULT  hr = D3D_OK;
5067     WINED3DVIEWPORT viewport;
5068
5069     TRACE("(%p) Swapping rendertarget\n",This);
5070     if (RenderTargetIndex > 0) {
5071         FIXME("(%p) Render targets other than the first are not supported\n",This);
5072         RenderTargetIndex = 0;
5073     }
5074
5075     /* MSDN says that null disables the render target
5076     but a device must always be associated with a render target
5077     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5078
5079     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5080     for more details
5081     */
5082     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5083         FIXME("Trying to set render target 0 to NULL\n");
5084         return D3DERR_INVALIDCALL;
5085     }
5086     /* TODO: replace Impl* usage with interface usage */
5087     if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5088         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);
5089         return D3DERR_INVALIDCALL;
5090     }
5091     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5092      *        builds, but I think wine counts as a 'debug' build for now.
5093       ******************************/
5094     /* If we are trying to set what we already have, don't bother */
5095     if (pRenderTarget == This->renderTarget) {
5096         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5097     } else {
5098         /* Otherwise, set the render target up */
5099
5100         if (FALSE == This->sceneEnded) {
5101             IWineD3DDevice_EndScene(iface);
5102         }
5103         TRACE("clearing renderer\n");
5104         /* IWineD3DDeviceImpl_CleanRender(iface); */
5105         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5106         depending on the renter target implementation being used.
5107         A shared context implementation will share all buffers between all rendertargets (including swapchains),
5108         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5109         stencil buffer and incure an extra memory overhead */
5110         hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5111     }
5112
5113     if (SUCCEEDED(hr)) {
5114         /* Finally, reset the viewport as the MSDN states. */
5115         /* TODO: Replace impl usage */
5116         viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5117         viewport.Width  = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5118         viewport.X      = 0;
5119         viewport.Y      = 0;
5120         viewport.MaxZ   = 1.0f;
5121         viewport.MinZ   = 0.0f;
5122         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5123     } else {
5124         FIXME("Unknown error setting the render target\n");
5125     }
5126     This->sceneEnded = FALSE;
5127     return hr;
5128 }
5129
5130 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5131     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5132     HRESULT  hr = D3D_OK;
5133     IWineD3DSurface *tmp;
5134
5135     TRACE("(%p) Swapping z-buffer\n",This);
5136
5137     if (pNewZStencil == This->stencilBufferTarget) {
5138         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5139     } else {
5140         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5141         * depending on the renter target implementation being used.
5142         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5143         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5144         * stencil buffer and incure an extra memory overhead
5145          ******************************************************/
5146
5147
5148         tmp = This->stencilBufferTarget;
5149         This->stencilBufferTarget = pNewZStencil;
5150         /* should we be calling the parent or the wined3d surface? */
5151         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5152         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5153         hr = D3D_OK;
5154         /** TODO: glEnable/glDisable on depth/stencil    depending on
5155          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
5156           **********************************************************/
5157     }
5158
5159     return hr;
5160 }
5161
5162
5163 /* Internal functions not in DirectX */
5164  /** TODO: move this off to the opengl context manager
5165  *(the swapchain doesn't need to know anything about offscreen rendering!)
5166   ****************************************************/
5167
5168 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5169 {
5170     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5171
5172     TRACE("(%p), %p\n", This, swapchain);
5173
5174     if (swapchain->win != swapchain->drawable) {
5175         /* Set everything back the way it ws */
5176         swapchain->render_ctx = swapchain->glCtx;
5177         swapchain->drawable   = swapchain->win;
5178     }
5179     return D3D_OK;
5180 }
5181
5182 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5183 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5184     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5185     int i;
5186     unsigned int width;
5187     unsigned int height;
5188     WINED3DFORMAT format;
5189     WINED3DSURFACE_DESC surfaceDesc;
5190     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5191     surfaceDesc.Width  = &width;
5192     surfaceDesc.Height = &height;
5193     surfaceDesc.Format = &format;
5194     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5195     *context = NULL;
5196     /* I need a get width/height function (and should do something with the format) */
5197     for (i = 0; i < CONTEXT_CACHE; ++i) {
5198         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5199         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5200         the pSurface can be set to 0 allowing it to be reused from cache **/
5201         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5202           && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5203             *context = &This->contextCache[i];
5204             break;
5205         }
5206         if (This->contextCache[i].Width == 0) {
5207             This->contextCache[i].pSurface = pSurface;
5208             This->contextCache[i].Width    = width;
5209             This->contextCache[i].Height   = height;
5210             *context = &This->contextCache[i];
5211             break;
5212         }
5213     }
5214     if (i == CONTEXT_CACHE) {
5215         int minUsage = 0x7FFFFFFF; /* MAX_INT */
5216         glContext *dropContext = 0;
5217         for (i = 0; i < CONTEXT_CACHE; i++) {
5218             if (This->contextCache[i].usedcount < minUsage) {
5219                 dropContext = &This->contextCache[i];
5220                 minUsage = This->contextCache[i].usedcount;
5221             }
5222         }
5223         /* clean up the context (this doesn't work for ATI at the moment */
5224 #if 0
5225         glXDestroyContext(swapchain->display, dropContext->context);
5226         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5227 #endif
5228         FIXME("Leak\n");
5229         dropContext->Width = 0;
5230         dropContext->pSurface = pSurface;
5231         *context = dropContext;
5232     } else {
5233         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5234           for (i = 0; i < CONTEXT_CACHE; i++) {
5235              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5236           }
5237         }
5238     }
5239     if (*context != NULL)
5240         return D3D_OK;
5241     else
5242         return E_OUTOFMEMORY;
5243 }
5244
5245 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5246 * the functionality needs splitting up so that we don't do more than we should do.
5247 * this only seems to impact performance a little.
5248  ******************************/
5249 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5250                                                IWineD3DSurface *RenderSurface) {
5251     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5252
5253     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5254     HRESULT ret =  D3DERR_INVALIDCALL;
5255     IWineD3DSurface *tmp;
5256     /**
5257     * Currently only active for GLX >= 1.3
5258     * for others versions we'll have to use GLXPixmaps
5259     *
5260     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5261     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5262     * so only check OpenGL version
5263     * ..........................
5264     * I don't believe that it is a problem with NVidia headers,
5265     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5266     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5267     * ATI Note:
5268     * Your application will report GLX version 1.2 on glXQueryVersion.
5269     * However, it is safe to call the GLX 1.3 functions as described below.
5270     */
5271 #if defined(GL_VERSION_1_3)
5272
5273     /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5274     GLXFBConfig* cfgs = NULL;
5275     int nCfgs = 0;
5276     int attribs[256];
5277     int nAttribs = 0;
5278     IWineD3DSwapChain     *currentSwapchain;
5279     IWineD3DSwapChainImpl *swapchain;
5280     /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5281     * but switch them off if the StencilSurface is set to NULL
5282     ** *********************************************************/
5283     D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5284     D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5285
5286     /**TODO:
5287         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5288         it StencilSurface != NULL && zBufferTarget == NULL switch it on
5289     */
5290
5291 #define PUSH1(att)        attribs[nAttribs++] = (att);
5292 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5293
5294     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5295
5296     /** TODO: remove the reff to Impl (context manager should fix this!) **/
5297     IWineD3DSwapChainImpl *impSwapChain;
5298     IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5299     if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5300         ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5301     }
5302
5303     ENTER_GL();
5304
5305     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5306     PUSH2(GLX_X_RENDERABLE,  TRUE);
5307     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
5308     TRACE("calling makeglcfg\n");
5309     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5310     PUSH1(None);
5311
5312     TRACE("calling chooseFGConfig\n");
5313     cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5314                                                      attribs, &nCfgs);
5315
5316     if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5317         /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5318            why we failed and only show this message once! */
5319         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"); /**/
5320         nAttribs = 0;
5321         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5322        /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
5323         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
5324         PUSH2(GLX_DOUBLEBUFFER, FALSE);
5325         TRACE("calling makeglcfg\n");
5326         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5327         PUSH1(None);
5328         cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5329                                                         attribs, &nCfgs);
5330     }
5331
5332     if (NULL != cfgs) {
5333 #ifdef EXTRA_TRACES
5334         int i;
5335         for (i = 0; i < nCfgs; ++i) {
5336             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5337             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5338             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5339         }
5340
5341         if (NULL != This->renderTarget) {
5342             glFlush();
5343             vcheckGLcall("glFlush");
5344             /** This is only useful if the old render target was a swapchain,
5345             * we need to supercede this with a function that displays
5346             * the current buffer on the screen. This is easy to do in glx1.3 but
5347             * we need to do copy-write pixels in glx 1.2.
5348             ************************************************/
5349             glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5350
5351             printf("Hit Enter to get next frame ...\n");
5352             getchar();
5353         }
5354 #endif
5355     }
5356
5357     if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK) {
5358         /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5359         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
5360     }
5361
5362     /**
5363     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5364     *  renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5365      **********************************************************************/
5366     if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5367         /* We also need to make sure that the lights &co are also in the context of the swapchains */
5368         /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5369         TRACE("making swapchain active\n");
5370         if (RenderSurface != This->renderTarget) {
5371             if (RenderSurface ==  swapchain->backBuffer) {
5372             } else {
5373                 /* This could be flagged so that some operations work directly with the front buffer */
5374                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
5375             }
5376             if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5377             == False) {
5378                 TRACE("Error in setting current context: context %p drawable %ld !\n",
5379                        impSwapChain->glCtx, impSwapChain->win);
5380             }
5381
5382             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5383         }
5384         checkGLcall("glXMakeContextCurrent");
5385
5386         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5387     }
5388     else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5389
5390         /** ********************************************************************
5391         * This is a quickly hacked out implementation of offscreen textures.
5392         * It will work in most cases but there may be problems if the client
5393         * modifies the texture directly, or expects the contents of the rendertarget
5394         * to be persistent.
5395         *
5396         * There are some real speed vs compatibility issues here:
5397         *    we should really use a new context for every texture, but that eats ram.
5398         *    we should also be restoring the texture to the pbuffer but that eats CPU
5399         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5400         *    but if this means reusing the display backbuffer then we need to make sure that
5401         *    states are correctly preserved.
5402         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5403         * and gain a good performance increase at the cost of compatibility.
5404         * I would suggest that, when this is the case, a user configurable flag be made
5405         * available, allowing the user to choose the best emulated experience for them.
5406          *********************************************************************/
5407
5408         XVisualInfo *visinfo;
5409         glContext   *newContext;
5410
5411         /* Here were using a shared context model */
5412         if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5413             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5414         }
5415
5416         /* If the context doesn't exist then create a new one */
5417         /* TODO: This should really be part of findGlContext */
5418         if (NULL == newContext->context) {
5419
5420             TRACE("making new buffer\n");
5421             nAttribs = 0;
5422             PUSH2(GLX_PBUFFER_WIDTH,  newContext->Width);
5423             PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5424             PUSH1(None);
5425
5426             newContext->drawable  = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5427
5428             /** ****************************************
5429             *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5430             *they note:
5431             *   In future releases, we may provide the calls glXCreateNewContext,
5432             *   glXQueryDrawable and glXMakeContextCurrent.
5433             *    so until then we have to use glXGetVisualFromFBConfig &co..
5434             ********************************************/
5435
5436
5437             visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5438             if (!visinfo) {
5439                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5440             } else {
5441                 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx,  GL_TRUE);
5442                 XFree(visinfo);
5443             }
5444         }
5445         if (NULL == newContext || NULL == newContext->context) {
5446             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5447         } else {
5448             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5449             if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5450                 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5451             }
5452
5453             /* Clean up the old context */
5454             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5455             /* Set the current context of the swapchain to the new context */
5456             impSwapChain->drawable   = newContext->drawable;
5457             impSwapChain->render_ctx = newContext->context;
5458         }
5459     }
5460
5461 #if 1 /* Apply the stateblock to the new context
5462 FIXME: This is a bit of a hack, each context should know it's own state,
5463 the directX current directX state should then be applied to the context */
5464     {
5465         BOOL oldRecording;
5466         IWineD3DStateBlockImpl *oldUpdateStateBlock;
5467         oldUpdateStateBlock = This->updateStateBlock;
5468         oldRecording= This->isRecordingState;
5469         This->isRecordingState = FALSE;
5470         This->updateStateBlock = This->stateBlock;
5471         IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5472
5473         This->isRecordingState = oldRecording;
5474         This->updateStateBlock = oldUpdateStateBlock;
5475     }
5476 #endif
5477
5478
5479     /* clean up the current rendertargets swapchain (if it belonged to one) */
5480     if (currentSwapchain != NULL) {
5481         IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5482     }
5483
5484     /* Were done with the opengl context management, setup the rendertargets */
5485
5486     tmp = This->renderTarget;
5487     This->renderTarget = RenderSurface;
5488     IWineD3DSurface_AddRef(This->renderTarget);
5489     IWineD3DSurface_Release(tmp);
5490
5491
5492
5493     {
5494         DWORD value;
5495         /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5496         /* Check that the container is not a swapchain member */
5497
5498         IWineD3DSwapChain *tmpSwapChain;
5499         if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5500             This->renderUpsideDown = TRUE;
5501         }else{
5502             This->renderUpsideDown = FALSE;
5503             IWineD3DSwapChain_Release(tmpSwapChain);
5504         }
5505         /* Force updating the cull mode */
5506         TRACE("setting render state\n");
5507         IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5508         IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5509
5510         /* Force updating projection matrix */
5511         This->last_was_rhw = FALSE;
5512         This->proj_valid = FALSE;
5513     }
5514
5515     ret = D3D_OK;
5516
5517     if (cfgs != NULL) {
5518         XFree(cfgs);
5519     } else {
5520         ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5521             debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5522     }
5523
5524 #undef PUSH1
5525 #undef PUSH2
5526     if ( NULL != impSwapChain) {
5527         IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5528     }
5529     LEAVE_GL();
5530
5531 #endif
5532     return ret;
5533 }
5534
5535 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5536                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5537     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5538     /* TODO: the use of Impl is deprecated. */
5539     /* some basic validation checks */
5540     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5541
5542     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5543
5544     if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5545       ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5546       return D3DERR_INVALIDCALL;
5547     }
5548     if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5549       ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5550       return D3DERR_INVALIDCALL;
5551     }
5552     /* TODO: make the cursor 'real' */
5553
5554     This->xHotSpot = XHotSpot;
5555     This->yHotSpot = YHotSpot;
5556
5557     return D3D_OK;
5558 }
5559
5560 void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5561     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5562     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5563
5564     This->xScreenSpace = XScreenSpace;
5565     This->yScreenSpace = YScreenSpace;
5566
5567     return;
5568
5569 }
5570
5571 BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5572     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5573     TRACE("(%p) : visible(%d)\n", This, bShow);
5574
5575     This->bCursorVisible = bShow;
5576
5577     return D3D_OK;
5578 }
5579
5580 HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5581     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5582     FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5583     return D3D_OK;
5584 }
5585
5586
5587 HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5588     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5589     /** FIXME: Resource tracking needs to be done,
5590     * The closes we can do to this is set the priorities of all managed textures low
5591     * and then reset them.
5592      ***********************************************************/
5593     FIXME("(%p) : stub\n", This);
5594     return D3D_OK;
5595 }
5596
5597 HRESULT  WINAPI  IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5598     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5599     /** FIXME: Resource trascking needs to be done.
5600     * in effect this pulls all non only default
5601     * textures out of video memory and deletes all glTextures (glDeleteTextures)
5602     * and should clear down the context and set it up according to pPresentationParameters
5603      ***********************************************************/
5604     FIXME("(%p) : stub\n", This);
5605     return D3D_OK;
5606 }
5607
5608 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5609     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5610     /** FIXME: always true at the moment **/
5611     if(bEnableDialogs == FALSE) {
5612         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5613     }
5614     return D3D_OK;
5615 }
5616
5617
5618 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5619     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5620
5621     FIXME("(%p) : stub\n", This);
5622     /* Setup some reasonable defaults */
5623     pParameters->AdapterOrdinal = 0; /* always for now */
5624     pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5625     pParameters->hFocusWindow = 0;
5626     pParameters->BehaviorFlags =0;
5627     return D3D_OK;
5628 }
5629
5630 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5631     IWineD3DSwapChain *swapchain;
5632     HRESULT hrc = D3D_OK;
5633
5634     TRACE("Relaying  to swapchain\n");
5635
5636     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5637         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5638         IWineD3DSwapChain_Release(swapchain);
5639     }
5640     return;
5641 }
5642
5643 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5644     IWineD3DSwapChain *swapchain;
5645     HRESULT hrc = D3D_OK;
5646
5647     TRACE("Relaying  to swapchain\n");
5648
5649     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5650         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5651         IWineD3DSwapChain_Release(swapchain);
5652     }
5653     return;
5654 }
5655
5656
5657 /** ********************************************************
5658 *   Notification functions
5659 ** ********************************************************/
5660 /** This function must be called in the release of a resource when ref == 0,
5661 * the contents of resource must still be correct,
5662 * any handels to other resource held by the caller must be closed
5663 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5664  *****************************************************/
5665 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5666     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5667     ResourceList* resourceList;
5668
5669     TRACE("(%p) : resource %p\n", This, resource);
5670 #if 0
5671     EnterCriticalSection(&resourceStoreCriticalSection);
5672 #endif
5673     /* add a new texture to the frot of the linked list */
5674     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5675     resourceList->resource = resource;
5676
5677     /* Get the old head */
5678     resourceList->next = This->resources;
5679
5680     This->resources = resourceList;
5681     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5682
5683 #if 0
5684     LeaveCriticalSection(&resourceStoreCriticalSection);
5685 #endif
5686     return;
5687 }
5688
5689 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5690     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5691     ResourceList* resourceList = NULL;
5692     ResourceList* previousResourceList = NULL;
5693     
5694     TRACE("(%p) : resource %p\n", This, resource);
5695
5696 #if 0
5697     EnterCriticalSection(&resourceStoreCriticalSection);
5698 #endif
5699     resourceList = This->resources;
5700
5701     while (resourceList != NULL) {
5702         if(resourceList->resource == resource) break;
5703         previousResourceList = resourceList;
5704         resourceList = resourceList->next;
5705     }
5706
5707     if (resourceList == NULL) {
5708         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5709 #if 0
5710         LeaveCriticalSection(&resourceStoreCriticalSection);
5711 #endif
5712         return;
5713     } else {
5714             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5715     }
5716     /* make sure we don't leave a hole in the list */
5717     if (previousResourceList != NULL) {
5718         previousResourceList->next = resourceList->next;
5719     } else {
5720         This->resources = resourceList->next;
5721     }
5722
5723 #if 0
5724     LeaveCriticalSection(&resourceStoreCriticalSection);
5725 #endif
5726     return;
5727 }
5728
5729
5730 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5731     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5732     int counter;
5733
5734     TRACE("(%p) : resource %p\n", This, resource);
5735     switch(IWineD3DResource_GetType(resource)){
5736         case D3DRTYPE_SURFACE:
5737         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
5738         break;
5739         case D3DRTYPE_TEXTURE:
5740         case D3DRTYPE_CUBETEXTURE:
5741         case D3DRTYPE_VOLUMETEXTURE:
5742                 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5743                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5744                         IUnknown *textureParent;
5745                         IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5746                         /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5747                         FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5748                         IUnknown_Release(textureParent);
5749                         This->stateBlock->textures[counter] = NULL;
5750                     }
5751                     if (This->updateStateBlock != This->stateBlock ){
5752                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5753                             IUnknown *textureParent;
5754                             IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5755                             /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5756                             FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5757                             IUnknown_Release(textureParent);
5758                             This->updateStateBlock->textures[counter] = NULL;
5759                         }
5760                     }
5761                 }
5762         break;
5763         case D3DRTYPE_VOLUME:
5764         /* TODO: nothing really? */
5765         break;
5766         case D3DRTYPE_VERTEXBUFFER:
5767         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5768         {
5769             int streamNumber;
5770             TRACE("Cleaning up stream pointers\n");
5771
5772             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5773                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5774                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5775                 */
5776                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5777                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5778                         FIXME("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
5779                         This->updateStateBlock->streamSource[streamNumber] = 0;
5780                         /* Set changed flag? */
5781                     }
5782                 }
5783                 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) */
5784                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5785                         TRACE("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
5786                         This->stateBlock->streamSource[streamNumber] = 0;
5787                     }
5788                 }
5789 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5790                  else { /* This shouldn't happen */
5791                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5792                 }
5793 #endif
5794
5795             }
5796         }
5797         break;
5798         case D3DRTYPE_INDEXBUFFER:
5799         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5800         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5801             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5802                 This->updateStateBlock->pIndexData =  NULL;
5803             }
5804         }
5805         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5806             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5807                 This->stateBlock->pIndexData =  NULL;
5808             }
5809         }
5810
5811         break;
5812         default:
5813         FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5814         break;
5815     }
5816
5817
5818     /* Remove the resoruce from the resourceStore */
5819     IWineD3DDeviceImpl_RemoveResource(iface, resource);
5820
5821     TRACE("Resource released\n");
5822
5823 }
5824
5825
5826 /** This function is to be called by the swapchain when it is released and it's ref = 0
5827  *****************************************************/
5828 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5829     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5830     SwapChainList **nextSwapchain;
5831     nextSwapchain = &This->swapchains;
5832
5833     /* Check to see if the swapchian is being used as the render target */
5834     if (This->renderTarget != NULL) {
5835         IWineD3DSurface *swapchainBackBuffer;
5836
5837         IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5838         if (This->renderTarget == swapchainBackBuffer) {
5839             /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5840             FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5841         }
5842     }
5843
5844     /* Go through the swapchain list and try to find the swapchain being released */
5845     while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
5846         nextSwapchain = &(*nextSwapchain)->next;
5847     }
5848
5849     /* Check to see if we found the swapchain */
5850     if (NULL != *nextSwapchain) {
5851         /* We found the swapchain so remove it from the list */
5852         TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
5853         HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
5854         *nextSwapchain = (*nextSwapchain)->next;
5855     } else {
5856         /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
5857         FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
5858     }
5859
5860     TRACE("swapchain (%p) released\n", swapChain);
5861     return;
5862 }
5863
5864 /**********************************************************
5865  * IWineD3DDevice VTbl follows
5866  **********************************************************/
5867
5868 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5869 {
5870     /*** IUnknown methods ***/
5871     IWineD3DDeviceImpl_QueryInterface,
5872     IWineD3DDeviceImpl_AddRef,
5873     IWineD3DDeviceImpl_Release,
5874     /*** IWineD3DDevice methods ***/
5875     IWineD3DDeviceImpl_GetParent,
5876     /*** Creation methods**/
5877     IWineD3DDeviceImpl_CreateVertexBuffer,
5878     IWineD3DDeviceImpl_CreateIndexBuffer,
5879     IWineD3DDeviceImpl_CreateStateBlock,
5880     IWineD3DDeviceImpl_CreateSurface,
5881     IWineD3DDeviceImpl_CreateTexture,
5882     IWineD3DDeviceImpl_CreateVolumeTexture,
5883     IWineD3DDeviceImpl_CreateVolume,
5884     IWineD3DDeviceImpl_CreateCubeTexture,
5885     IWineD3DDeviceImpl_CreateQuery,
5886     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5887     IWineD3DDeviceImpl_CreateVertexDeclaration,
5888     IWineD3DDeviceImpl_CreateVertexShader,
5889     IWineD3DDeviceImpl_CreatePixelShader,
5890     /*** Odd functions **/
5891     IWineD3DDeviceImpl_EvictManagedResources,
5892     IWineD3DDeviceImpl_GetAvailableTextureMem,
5893     IWineD3DDeviceImpl_GetBackBuffer,
5894     IWineD3DDeviceImpl_GetCreationParameters,
5895     IWineD3DDeviceImpl_GetDeviceCaps,
5896     IWineD3DDeviceImpl_GetDirect3D,
5897     IWineD3DDeviceImpl_GetDisplayMode,
5898     IWineD3DDeviceImpl_GetNumberOfSwapChains,
5899     IWineD3DDeviceImpl_GetRasterStatus,
5900     IWineD3DDeviceImpl_GetSwapChain,
5901     IWineD3DDeviceImpl_Reset,
5902     IWineD3DDeviceImpl_SetDialogBoxMode,
5903     IWineD3DDeviceImpl_SetCursorProperties,
5904     IWineD3DDeviceImpl_SetCursorPosition,
5905     IWineD3DDeviceImpl_ShowCursor,
5906     IWineD3DDeviceImpl_TestCooperativeLevel,
5907     /*** Getters and setters **/
5908     IWineD3DDeviceImpl_SetClipPlane,
5909     IWineD3DDeviceImpl_GetClipPlane,
5910     IWineD3DDeviceImpl_SetClipStatus,
5911     IWineD3DDeviceImpl_GetClipStatus,
5912     IWineD3DDeviceImpl_SetCurrentTexturePalette,
5913     IWineD3DDeviceImpl_GetCurrentTexturePalette,
5914     IWineD3DDeviceImpl_SetDepthStencilSurface,
5915     IWineD3DDeviceImpl_GetDepthStencilSurface,
5916     IWineD3DDeviceImpl_SetFVF,
5917     IWineD3DDeviceImpl_GetFVF,
5918     IWineD3DDeviceImpl_SetGammaRamp,
5919     IWineD3DDeviceImpl_GetGammaRamp,
5920     IWineD3DDeviceImpl_SetIndices,
5921     IWineD3DDeviceImpl_GetIndices,
5922     IWineD3DDeviceImpl_SetLight,
5923     IWineD3DDeviceImpl_GetLight,
5924     IWineD3DDeviceImpl_SetLightEnable,
5925     IWineD3DDeviceImpl_GetLightEnable,
5926     IWineD3DDeviceImpl_SetMaterial,
5927     IWineD3DDeviceImpl_GetMaterial,
5928     IWineD3DDeviceImpl_SetNPatchMode,
5929     IWineD3DDeviceImpl_GetNPatchMode,
5930     IWineD3DDeviceImpl_SetPaletteEntries,
5931     IWineD3DDeviceImpl_GetPaletteEntries,
5932     IWineD3DDeviceImpl_SetPixelShader,
5933     IWineD3DDeviceImpl_GetPixelShader,
5934     IWineD3DDeviceImpl_SetPixelShaderConstantB,
5935     IWineD3DDeviceImpl_GetPixelShaderConstantB,
5936     IWineD3DDeviceImpl_SetPixelShaderConstantI,
5937     IWineD3DDeviceImpl_GetPixelShaderConstantI,
5938     IWineD3DDeviceImpl_SetPixelShaderConstantF,
5939     IWineD3DDeviceImpl_GetPixelShaderConstantF,
5940     IWineD3DDeviceImpl_SetRenderState,
5941     IWineD3DDeviceImpl_GetRenderState,
5942     IWineD3DDeviceImpl_SetRenderTarget,
5943     IWineD3DDeviceImpl_GetRenderTarget,
5944     IWineD3DDeviceImpl_SetSamplerState,
5945     IWineD3DDeviceImpl_GetSamplerState,
5946     IWineD3DDeviceImpl_SetScissorRect,
5947     IWineD3DDeviceImpl_GetScissorRect,
5948     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5949     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5950     IWineD3DDeviceImpl_SetStreamSource,
5951     IWineD3DDeviceImpl_GetStreamSource,
5952     IWineD3DDeviceImpl_SetStreamSourceFreq,
5953     IWineD3DDeviceImpl_GetStreamSourceFreq,
5954     IWineD3DDeviceImpl_SetTexture,
5955     IWineD3DDeviceImpl_GetTexture,
5956     IWineD3DDeviceImpl_SetTextureStageState,
5957     IWineD3DDeviceImpl_GetTextureStageState,
5958     IWineD3DDeviceImpl_SetTransform,
5959     IWineD3DDeviceImpl_GetTransform,
5960     IWineD3DDeviceImpl_SetVertexDeclaration,
5961     IWineD3DDeviceImpl_GetVertexDeclaration,
5962     IWineD3DDeviceImpl_SetVertexShader,
5963     IWineD3DDeviceImpl_GetVertexShader,
5964     IWineD3DDeviceImpl_SetVertexShaderConstantB,
5965     IWineD3DDeviceImpl_GetVertexShaderConstantB,
5966     IWineD3DDeviceImpl_SetVertexShaderConstantI,
5967     IWineD3DDeviceImpl_GetVertexShaderConstantI,
5968     IWineD3DDeviceImpl_SetVertexShaderConstantF,
5969     IWineD3DDeviceImpl_GetVertexShaderConstantF,
5970     IWineD3DDeviceImpl_SetViewport,
5971     IWineD3DDeviceImpl_GetViewport,
5972     IWineD3DDeviceImpl_MultiplyTransform,
5973     IWineD3DDeviceImpl_ValidateDevice,
5974     IWineD3DDeviceImpl_ProcessVertices,
5975     /*** State block ***/
5976     IWineD3DDeviceImpl_BeginStateBlock,
5977     IWineD3DDeviceImpl_EndStateBlock,
5978     /*** Scene management ***/
5979     IWineD3DDeviceImpl_BeginScene,
5980     IWineD3DDeviceImpl_EndScene,
5981     IWineD3DDeviceImpl_Present,
5982     IWineD3DDeviceImpl_Clear,
5983     /*** Drawing ***/
5984     IWineD3DDeviceImpl_DrawPrimitive,
5985     IWineD3DDeviceImpl_DrawIndexedPrimitive,
5986     IWineD3DDeviceImpl_DrawPrimitiveUP,
5987     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5988     IWineD3DDeviceImpl_DrawRectPatch,
5989     IWineD3DDeviceImpl_DrawTriPatch,
5990     IWineD3DDeviceImpl_DeletePatch,
5991     IWineD3DDeviceImpl_ColorFill,
5992     IWineD3DDeviceImpl_UpdateTexture,
5993     IWineD3DDeviceImpl_UpdateSurface,
5994     IWineD3DDeviceImpl_StretchRect,
5995     IWineD3DDeviceImpl_GetRenderTargetData,
5996     IWineD3DDeviceImpl_GetFrontBufferData,
5997     /*** Internal use IWineD3DDevice methods ***/
5998     IWineD3DDeviceImpl_SetupTextureStates,
5999     /*** object tracking ***/
6000     IWineD3DDeviceImpl_SwapChainReleased,
6001     IWineD3DDeviceImpl_ResourceReleased
6002 };
6003
6004
6005 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6006     WINED3DRS_ALPHABLENDENABLE   ,
6007     WINED3DRS_ALPHAFUNC          ,
6008     WINED3DRS_ALPHAREF           ,
6009     WINED3DRS_ALPHATESTENABLE    ,
6010     WINED3DRS_BLENDOP            ,
6011     WINED3DRS_COLORWRITEENABLE   ,
6012     WINED3DRS_DESTBLEND          ,
6013     WINED3DRS_DITHERENABLE       ,
6014     WINED3DRS_FILLMODE           ,
6015     WINED3DRS_FOGDENSITY         ,
6016     WINED3DRS_FOGEND             ,
6017     WINED3DRS_FOGSTART           ,
6018     WINED3DRS_LASTPIXEL          ,
6019     WINED3DRS_SHADEMODE          ,
6020     WINED3DRS_SRCBLEND           ,
6021     WINED3DRS_STENCILENABLE      ,
6022     WINED3DRS_STENCILFAIL        ,
6023     WINED3DRS_STENCILFUNC        ,
6024     WINED3DRS_STENCILMASK        ,
6025     WINED3DRS_STENCILPASS        ,
6026     WINED3DRS_STENCILREF         ,
6027     WINED3DRS_STENCILWRITEMASK   ,
6028     WINED3DRS_STENCILZFAIL       ,
6029     WINED3DRS_TEXTUREFACTOR      ,
6030     WINED3DRS_WRAP0              ,
6031     WINED3DRS_WRAP1              ,
6032     WINED3DRS_WRAP2              ,
6033     WINED3DRS_WRAP3              ,
6034     WINED3DRS_WRAP4              ,
6035     WINED3DRS_WRAP5              ,
6036     WINED3DRS_WRAP6              ,
6037     WINED3DRS_WRAP7              ,
6038     WINED3DRS_ZENABLE            ,
6039     WINED3DRS_ZFUNC              ,
6040     WINED3DRS_ZWRITEENABLE
6041 };
6042
6043 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6044     WINED3DTSS_ADDRESSW              ,
6045     WINED3DTSS_ALPHAARG0             ,
6046     WINED3DTSS_ALPHAARG1             ,
6047     WINED3DTSS_ALPHAARG2             ,
6048     WINED3DTSS_ALPHAOP               ,
6049     WINED3DTSS_BUMPENVLOFFSET        ,
6050     WINED3DTSS_BUMPENVLSCALE         ,
6051     WINED3DTSS_BUMPENVMAT00          ,
6052     WINED3DTSS_BUMPENVMAT01          ,
6053     WINED3DTSS_BUMPENVMAT10          ,
6054     WINED3DTSS_BUMPENVMAT11          ,
6055     WINED3DTSS_COLORARG0             ,
6056     WINED3DTSS_COLORARG1             ,
6057     WINED3DTSS_COLORARG2             ,
6058     WINED3DTSS_COLOROP               ,
6059     WINED3DTSS_RESULTARG             ,
6060     WINED3DTSS_TEXCOORDINDEX         ,
6061     WINED3DTSS_TEXTURETRANSFORMFLAGS
6062 };
6063
6064 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6065     WINED3DSAMP_ADDRESSU         ,
6066     WINED3DSAMP_ADDRESSV         ,
6067     WINED3DSAMP_ADDRESSW         ,
6068     WINED3DSAMP_BORDERCOLOR      ,
6069     WINED3DSAMP_MAGFILTER        ,
6070     WINED3DSAMP_MINFILTER        ,
6071     WINED3DSAMP_MIPFILTER        ,
6072     WINED3DSAMP_MIPMAPLODBIAS    ,
6073     WINED3DSAMP_MAXMIPLEVEL      ,
6074     WINED3DSAMP_MAXANISOTROPY    ,
6075     WINED3DSAMP_SRGBTEXTURE      ,
6076     WINED3DSAMP_ELEMENTINDEX
6077 };
6078
6079 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6080     WINED3DRS_AMBIENT                       ,
6081     WINED3DRS_AMBIENTMATERIALSOURCE         ,
6082     WINED3DRS_CLIPPING                      ,
6083     WINED3DRS_CLIPPLANEENABLE               ,
6084     WINED3DRS_COLORVERTEX                   ,
6085     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
6086     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
6087     WINED3DRS_FOGDENSITY                    ,
6088     WINED3DRS_FOGEND                        ,
6089     WINED3DRS_FOGSTART                      ,
6090     WINED3DRS_FOGTABLEMODE                  ,
6091     WINED3DRS_FOGVERTEXMODE                 ,
6092     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
6093     WINED3DRS_LIGHTING                      ,
6094     WINED3DRS_LOCALVIEWER                   ,
6095     WINED3DRS_MULTISAMPLEANTIALIAS          ,
6096     WINED3DRS_MULTISAMPLEMASK               ,
6097     WINED3DRS_NORMALIZENORMALS              ,
6098     WINED3DRS_PATCHEDGESTYLE                ,
6099     WINED3DRS_POINTSCALE_A                  ,
6100     WINED3DRS_POINTSCALE_B                  ,
6101     WINED3DRS_POINTSCALE_C                  ,
6102     WINED3DRS_POINTSCALEENABLE              ,
6103     WINED3DRS_POINTSIZE                     ,
6104     WINED3DRS_POINTSIZE_MAX                 ,
6105     WINED3DRS_POINTSIZE_MIN                 ,
6106     WINED3DRS_POINTSPRITEENABLE             ,
6107     WINED3DRS_RANGEFOGENABLE                ,
6108     WINED3DRS_SPECULARMATERIALSOURCE        ,
6109     WINED3DRS_TWEENFACTOR                   ,
6110     WINED3DRS_VERTEXBLEND
6111 };
6112
6113 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6114     WINED3DTSS_TEXCOORDINDEX         ,
6115     WINED3DTSS_TEXTURETRANSFORMFLAGS
6116 };
6117
6118 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6119     WINED3DSAMP_DMAPOFFSET
6120 };