Moved mciavi32 to the top-level dlls directory.
[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     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
3386     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3387
3388     /* Handle recording of state blocks */
3389     if (This->isRecordingState) {
3390         TRACE("Recording... not performing anything\n");
3391         return D3D_OK;
3392     }
3393
3394     return D3D_OK;
3395 }
3396
3397 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3398     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3399     /** TODO: check that sampler is in  range **/
3400     *Value = This->updateStateBlock->samplerState[Sampler][Type];
3401     TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3402
3403     return D3D_OK;
3404 }
3405
3406 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3407     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3408     ENTER_GL();
3409
3410     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3411     TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3412     glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3413     LEAVE_GL();
3414
3415     return D3D_OK;
3416 }
3417
3418 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3419     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3420     GLint scissorBox[4];
3421
3422     ENTER_GL();
3423     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3424     glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3425     pRect->left = scissorBox[1];
3426     pRect->top = scissorBox[2];
3427     pRect->right = scissorBox[1] + scissorBox[3];
3428     pRect->bottom = scissorBox[2] + scissorBox[4];
3429     TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3430     LEAVE_GL();
3431     return D3D_OK;
3432 }
3433
3434 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3435     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3436
3437     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3438
3439     /* TODO: what about recording stateblocks? */
3440     if (NULL != pDecl) {
3441         IWineD3DVertexDeclaration_AddRef(pDecl);
3442     }
3443     if (NULL != This->updateStateBlock->vertexDecl) {
3444       IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3445     }
3446     This->updateStateBlock->vertexDecl = pDecl;
3447     This->updateStateBlock->changed.vertexDecl = TRUE;
3448     This->updateStateBlock->set.vertexDecl = TRUE;
3449     return D3D_OK;
3450 }
3451
3452 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3453     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3454
3455     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3456
3457     *ppDecl = This->updateStateBlock->vertexDecl;
3458     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3459     return D3D_OK;
3460 }
3461
3462 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3463     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3464     IWineD3DVertexShader *oldShader = This->updateStateBlock->vertexShader;
3465
3466     This->updateStateBlock->vertexShader = pShader;
3467     This->updateStateBlock->changed.vertexShader = TRUE;
3468     This->updateStateBlock->set.vertexShader = TRUE;
3469
3470     if (This->isRecordingState) {
3471         TRACE("Recording... not performing anything\n");
3472         return D3D_OK;
3473     }
3474
3475     if (pShader != NULL) {
3476         IUnknown *newVertexShaderParent;
3477         /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
3478         TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3479         IWineD3DVertexShader_GetParent(pShader, &newVertexShaderParent);
3480     } else {
3481         TRACE("Clear down the shader\n");
3482     }
3483     if (oldShader != NULL) {
3484         IUnknown *oldVertexShaderParent;
3485         IWineD3DVertexShader_GetParent(oldShader, &oldVertexShaderParent);
3486         IUnknown_Release(oldVertexShaderParent);
3487         IUnknown_Release(oldVertexShaderParent);
3488     }
3489     /**
3490      * TODO: merge HAL shaders context switching from prototype
3491      */
3492     return D3D_OK;
3493 }
3494
3495 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3496     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3497
3498     if (NULL == ppShader) {
3499         return D3DERR_INVALIDCALL;
3500     }
3501     *ppShader = This->stateBlock->vertexShader;
3502     if( NULL != *ppShader)
3503         IWineD3DVertexShader_AddRef(*ppShader);
3504
3505     TRACE("(%p) : returning %p\n", This, *ppShader);
3506     return D3D_OK;
3507 }
3508
3509 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3510 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3511 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3512     return D3DERR_INVALIDCALL; \
3513 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3514
3515 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3516 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3517 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3518     return D3DERR_INVALIDCALL; \
3519 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3520 This->updateStateBlock->changed.vertexShader = TRUE; \
3521 This->updateStateBlock->set.vertexShader = TRUE;
3522
3523 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL  *pConstantData, UINT BoolCount){
3524     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3525     static BOOL showFixmes = TRUE;
3526     SET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3527 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3528     memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTB, BoolCount);
3529 #endif
3530     /* clean out the other constants? */
3531     if(showFixmes || TRUE) {
3532         FIXME("(%p) : stub\n", This);
3533         showFixmes = FALSE;
3534     }
3535     return D3D_OK;
3536 }
3537
3538 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3539     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3540     static BOOL showFixmes = TRUE;
3541 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3542     for (i = 0; i < BoolCount; i++ ) {
3543         if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTB) {
3544             /* the constant for this register isn't a boolean */
3545             return D3DERR_INVALIDCALL;
3546         }
3547     }
3548 #endif
3549     GET_SHADER_CONSTANT(vertexShaderConstantB, BoolCount, 1);
3550     if(showFixmes || TRUE) {
3551         FIXME("(%p) : stub\n", This);
3552         showFixmes = FALSE;
3553     }
3554     return D3D_OK;
3555 }
3556
3557 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3558     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3559     static BOOL showFixmes = TRUE;
3560 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3561     memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTI, Vector4iCount);
3562 #endif
3563     SET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3564     /* clean out the other constants? */
3565     if(showFixmes || TRUE) {
3566         FIXME("(%p) : stub\n", This);
3567         showFixmes = FALSE;
3568     }
3569     return D3D_OK;
3570 }
3571
3572 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int         *pConstantData, UINT Vector4iCount){
3573     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3574     static BOOL showFixmes = TRUE;
3575 #if 0 /* TODO: a bitmap to say which constant type we should load */
3576     for (i = 0; i < Vector4iCount; i++ ) {
3577         if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTI) {
3578             /* the constant for this register isn't a boolean */
3579             return D3DERR_INVALIDCALL;
3580         }
3581     }
3582 #endif
3583     GET_SHADER_CONSTANT(vertexShaderConstantI, Vector4iCount, 4);
3584     if(showFixmes || TRUE) {
3585         FIXME("(%p) : stub\n", This);
3586         showFixmes = FALSE;
3587     }
3588     return D3D_OK;
3589 }
3590
3591 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3592     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3593     static BOOL showFixmes = TRUE;
3594 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3595     memset(This->updateStateBlock->vsibfBitmap + StartRegister, WINESHADER_CONSTANTF, Vector4fCount);
3596 #endif
3597     SET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3598     /* clean out the other constants? */
3599     if(showFixmes) {
3600         TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3601         showFixmes = FALSE;
3602     }
3603     return D3D_OK;
3604 }
3605
3606 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float       *pConstantData, UINT Vector4fCount){
3607     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3608     static BOOL showFixmes = TRUE;
3609 #if 0 /* TODO: a bitmap to say which constant type we should load */
3610     for (i = 0; i < Vector4fCount; i++ ) {
3611         if (This->updateStateBlock->vsibfBitmap[StartRegister + i] != WINESHADER_CONSTANTF) {
3612             /* the constant for this register isn't a boolean */
3613             return D3DERR_INVALIDCALL;
3614         }
3615     }
3616 #endif
3617     GET_SHADER_CONSTANT(vertexShaderConstantF, Vector4fCount, 4);
3618     if(showFixmes) {
3619         TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This);
3620         showFixmes = FALSE;
3621     }
3622     return D3D_OK;
3623 }
3624
3625 #undef SET_SHADER_CONSTANT
3626 #undef GET_SHADER_CONSTANT
3627
3628
3629 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader  *pShader) {
3630     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3631     TRACE("(%p) : stub\n", This);
3632     return D3D_OK;
3633 }
3634
3635 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3636     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3637     TRACE("(%p) : stub\n", This);
3638     return D3D_OK;
3639 }
3640
3641
3642 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL   *pConstantData, UINT BoolCount) {
3643     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3644     TRACE("(%p) : stub\n", This);
3645     return D3D_OK;
3646 }
3647
3648 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL         *pConstantData, UINT BoolCount) {
3649     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3650     TRACE("(%p) : stub\n", This);
3651     return D3D_OK;
3652 }
3653
3654 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int    *pConstantData, UINT Vector4iCount) {
3655     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3656     TRACE("(%p) : stub\n", This);
3657     return D3D_OK;
3658 }
3659
3660 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int          *pConstantData, UINT Vector4iCount) {
3661     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3662     TRACE("(%p) : stub\n", This);
3663     return D3D_OK;
3664 }
3665
3666 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float  *pConstantData, UINT Vector4fCount) {
3667     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3668     TRACE("(%p) : stub\n", This);
3669     return D3D_OK;
3670 }
3671
3672 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float        *pConstantData, UINT Vector4fCount) {
3673     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3674     TRACE("(%p) : stub\n", This);
3675     return D3D_OK;
3676 }
3677
3678 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3679     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3680     FIXME("(%p) : stub\n", This);
3681     return D3D_OK;
3682 }
3683
3684 /*****
3685  * Apply / Get / Set Texture Stage States
3686  * TODO: Verify against dx9 definitions
3687  *****/
3688
3689 /* 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 */
3690 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
3691     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3692     DWORD Value = This->updateStateBlock->textureState[Stage][Type];
3693     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3694
3695     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3696
3697     /* Check that the stage is within limits  */
3698     if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3699         TRACE("Attempt to access invalid texture rejected\n");
3700         return;
3701     }
3702
3703     ENTER_GL();
3704
3705     switch (Type) {
3706     case WINED3DTSS_ALPHAOP               :
3707     case WINED3DTSS_COLOROP               :
3708         /* nothing to do as moved to drawprim for now */
3709         break;
3710     case WINED3DTSS_ADDRESSW              :
3711 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
3712             if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
3713                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3714
3715             } else {
3716                 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
3717                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3718                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3719                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3720             }
3721 #endif
3722     case WINED3DTSS_TEXCOORDINDEX         :
3723         {
3724             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3725
3726             /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3727                   one flag, you can still specify an index value, which the system uses to
3728                   determine the texture wrapping mode.
3729                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3730                   means use the vertex position (camera-space) as the input texture coordinates
3731                   for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3732                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3733                   to the TEXCOORDINDEX value */
3734
3735             /**
3736              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3737              */
3738             switch (Value & 0xFFFF0000) {
3739             case D3DTSS_TCI_PASSTHRU:
3740                 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3741                 glDisable(GL_TEXTURE_GEN_S);
3742                 glDisable(GL_TEXTURE_GEN_T);
3743                 glDisable(GL_TEXTURE_GEN_R);
3744                 glDisable(GL_TEXTURE_GEN_Q);
3745                 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
3746                 break;
3747
3748             case D3DTSS_TCI_CAMERASPACEPOSITION:
3749                 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3750                     as the input texture coordinates for this stage's texture transformation. This
3751                     equates roughly to EYE_LINEAR                                                  */
3752                 {
3753                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3754                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3755                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3756                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3757                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3758     
3759                     glMatrixMode(GL_MODELVIEW);
3760                     glPushMatrix();
3761                     glLoadIdentity();
3762                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3763                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3764                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3765                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3766                     glPopMatrix();
3767     
3768                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3769                     glEnable(GL_TEXTURE_GEN_S);
3770                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3771                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3772                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3773                     glEnable(GL_TEXTURE_GEN_T);
3774                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3775                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3776                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3777                     glEnable(GL_TEXTURE_GEN_R);
3778                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3779                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3780                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3781                 }
3782                 break;
3783
3784             case D3DTSS_TCI_CAMERASPACENORMAL:
3785                 {
3786                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3787                         float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3788                         float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3789                         float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3790                         float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3791                         TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
3792         
3793                         glMatrixMode(GL_MODELVIEW);
3794                         glPushMatrix();
3795                         glLoadIdentity();
3796                         glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3797                         glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3798                         glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3799                         glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3800                         glPopMatrix();
3801         
3802                         glEnable(GL_TEXTURE_GEN_S);
3803                         checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3804                         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3805                         checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3806                         glEnable(GL_TEXTURE_GEN_T);
3807                         checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3808                         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3809                         checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3810                         glEnable(GL_TEXTURE_GEN_R);
3811                         checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3812                         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3813                         checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3814                     }
3815                 }
3816                 break;
3817
3818             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3819                 {
3820                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3821                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3822                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3823                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3824                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3825                     TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
3826     
3827                     glMatrixMode(GL_MODELVIEW);
3828                     glPushMatrix();
3829                     glLoadIdentity();
3830                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3831                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3832                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3833                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3834                     glPopMatrix();
3835     
3836                     glEnable(GL_TEXTURE_GEN_S);
3837                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3838                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3839                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3840                     glEnable(GL_TEXTURE_GEN_T);
3841                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3842                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3843                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3844                     glEnable(GL_TEXTURE_GEN_R);
3845                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3846                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3847                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3848                     }
3849                 }
3850                 break;
3851
3852             /* Unhandled types: */
3853             default:
3854                 /* Todo: */
3855                 /* ? disable GL_TEXTURE_GEN_n ? */
3856                 glDisable(GL_TEXTURE_GEN_S);
3857                 glDisable(GL_TEXTURE_GEN_T);
3858                 glDisable(GL_TEXTURE_GEN_R);
3859                 glDisable(GL_TEXTURE_GEN_Q);
3860                 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
3861                 break;
3862             }
3863         }
3864         break;
3865
3866         /* Unhandled */
3867     case WINED3DTSS_TEXTURETRANSFORMFLAGS :
3868         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);
3869         break;
3870
3871     case WINED3DTSS_BUMPENVMAT00          :
3872     case WINED3DTSS_BUMPENVMAT01          :
3873         TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
3874         break;
3875     case WINED3DTSS_BUMPENVMAT10          :
3876     case WINED3DTSS_BUMPENVMAT11          :
3877         TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
3878         break;
3879
3880     case WINED3DTSS_BUMPENVLSCALE         :
3881       TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3882       break;
3883
3884     case WINED3DTSS_BUMPENVLOFFSET        :
3885       TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3886       break;
3887
3888     case WINED3DTSS_RESULTARG             :
3889       TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3890       break;
3891
3892     default:
3893         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3894         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3895     }
3896
3897     LEAVE_GL();
3898
3899     return;
3900 }
3901
3902 /*****
3903  * Get / Set Texture Stage States
3904  * TODO: Verify against dx9 definitions
3905  *****/
3906 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3907     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3908
3909     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3910
3911     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3912
3913     /* Reject invalid texture units */
3914     if (Stage >= GL_LIMITS(textures)) {
3915         TRACE("Attempt to access invalid texture rejected\n");
3916         return D3DERR_INVALIDCALL;
3917     }
3918
3919     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3920     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
3921     This->updateStateBlock->textureState[Stage][Type]         = Value;
3922
3923     return D3D_OK;
3924 }
3925
3926 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3927     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3928     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3929     *pValue = This->updateStateBlock->textureState[Stage][Type];
3930     return D3D_OK;
3931 }
3932
3933 /*****
3934  * Get / Set Texture
3935  *****/
3936 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3937
3938     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3939     IWineD3DBaseTexture   *oldTexture;
3940
3941     oldTexture = This->updateStateBlock->textures[Stage];
3942     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3943
3944 #if 0 /* TODO: check so vertex textures */
3945     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
3946         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
3947         return D3D_OK;
3948     }
3949 #endif
3950
3951     /* Reject invalid texture units */
3952     if (Stage >= GL_LIMITS(textures) || Stage < 0) {
3953         WARN("Attempt to access invalid texture rejected\n");
3954         return D3DERR_INVALIDCALL;
3955     }
3956
3957     oldTexture = This->updateStateBlock->textures[Stage];
3958     TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
3959     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
3960
3961     This->updateStateBlock->set.textures[Stage]     = TRUE;
3962     This->updateStateBlock->changed.textures[Stage] = TRUE;
3963     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
3964     This->updateStateBlock->textures[Stage]         = pTexture;
3965
3966     /* Handle recording of state blocks */
3967     if (This->isRecordingState) {
3968         TRACE("Recording... not performing anything\n");
3969         return D3D_OK;
3970     }
3971
3972     /** NOTE: MSDN says that setTexture increases the reference count,
3973     * and the the application nust set the texture back to null (or have a leaky application),
3974     * This means we should pass the refcount upto the parent
3975      *******************************/
3976     if (NULL != This->updateStateBlock->textures[Stage]) {
3977         IUnknown *textureParent;
3978         IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
3979         /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
3980     }
3981
3982     if (NULL != oldTexture) {
3983         IUnknown *textureParent;
3984         IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
3985         IUnknown_Release(textureParent);
3986         IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
3987         oldTexture = NULL;
3988     }
3989
3990     return D3D_OK;
3991 }
3992
3993 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3994     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3995     TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */) \n", This, Stage, ppTexture);
3996
3997     /* Reject invalid texture units */
3998     if (Stage >= GL_LIMITS(textures)) {
3999         TRACE("Attempt to access invalid texture rejected\n");
4000         return D3DERR_INVALIDCALL;
4001     }
4002     *ppTexture=This->updateStateBlock->textures[Stage];
4003     if (*ppTexture)
4004         IWineD3DBaseTexture_AddRef(*ppTexture);
4005     else
4006         return D3DERR_INVALIDCALL;
4007     return D3D_OK;
4008 }
4009
4010 /*****
4011  * Get Back Buffer
4012  *****/
4013 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4014                                                 IWineD3DSurface **ppBackBuffer) {
4015     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4016     IWineD3DSwapChain *swapChain;
4017     HRESULT hr;
4018
4019     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4020
4021     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4022     if (hr == D3D_OK) {
4023         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4024             IWineD3DSwapChain_Release(swapChain);
4025     } else {
4026         *ppBackBuffer = NULL;
4027     }
4028     return hr;
4029 }
4030
4031 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4032     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4033     WARN("(%p) : stub, calling idirect3d for now\n", This);
4034     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4035 }
4036
4037 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4038     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4039     IWineD3DSwapChain *swapChain;
4040     HRESULT hr;
4041
4042     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4043     if (hr == D3D_OK) {
4044         hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4045         IWineD3DSwapChain_Release(swapChain);
4046     } else {
4047         FIXME("(%p) Error getting display mode\n", This);
4048     }
4049     return hr;
4050 }
4051 /*****
4052  * Stateblock related functions
4053  *****/
4054
4055 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4056     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4057     IWineD3DStateBlockImpl *object;
4058     TRACE("(%p)", This);
4059     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4060     if (NULL == object ) {
4061         FIXME("(%p)Error allocating memory for stateblock\n", This);
4062         return E_OUTOFMEMORY;
4063     }
4064     TRACE("(%p) creted object %p\n", This, object);
4065     object->wineD3DDevice= This;
4066     /** FIXME: object->parent       = parent; **/
4067     object->parent       = NULL;
4068     object->blockType    = WINED3DSBT_ALL;
4069     object->ref          = 1;
4070     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4071
4072     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4073     This->updateStateBlock = object;
4074     This->isRecordingState = TRUE;
4075
4076     TRACE("(%p) recording stateblock %p\n",This , object);
4077     return D3D_OK;
4078 }
4079
4080 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4081     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4082
4083     if (!This->isRecordingState) {
4084         FIXME("(%p) not recording! returning error\n", This);
4085         *ppStateBlock = NULL;
4086         return D3DERR_INVALIDCALL;
4087     }
4088
4089     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4090     This->isRecordingState = FALSE;
4091     This->updateStateBlock = This->stateBlock;
4092     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4093     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4094     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4095     return D3D_OK;
4096 }
4097
4098 /*****
4099  * Scene related functions
4100  *****/
4101 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4102     /* At the moment we have no need for any functionality at the beginning
4103        of a scene                                                          */
4104     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4105     TRACE("(%p) : stub\n", This);
4106     return D3D_OK;
4107 }
4108
4109 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4110     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4111     TRACE("(%p)\n", This);
4112     ENTER_GL();
4113     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4114     glFlush();
4115     checkGLcall("glFlush");
4116
4117     TRACE("End Scene\n");
4118     if(This->renderTarget != NULL) {
4119
4120         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4121         IUnknown *targetContainer = NULL;
4122         if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4123             || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4124             TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4125             /** always dirtify for now. we must find a better way to see that surface have been modified
4126             (Modifications should will only occur via draw-primitive, but we do need better locking
4127             switching to render-to-texture should remove the overhead though.
4128             */
4129             IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4130             IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4131             IWineD3DSurface_PreLoad(This->renderTarget);
4132             IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4133             IUnknown_Release(targetContainer);
4134         }
4135     }
4136     This->sceneEnded = TRUE;
4137     LEAVE_GL();
4138     return D3D_OK;
4139 }
4140
4141 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4142                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4143                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4144     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4145     IWineD3DSwapChain *swapChain = NULL;
4146     int i;
4147     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4148
4149     TRACE("(%p) Presenting the frame\n", This);
4150
4151     for(i = 0 ; i < swapchains ; i ++) {
4152
4153         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4154         TRACE("presentinng chain %d, %p\n", i, swapChain);
4155         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4156         IWineD3DSwapChain_Release(swapChain);
4157     }
4158
4159     return D3D_OK;
4160 }
4161
4162 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4163                                         DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4164     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4165
4166     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4167       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4168       when the depth-buffer format does not contain stencil buffer information, this method fails. */
4169     GLbitfield     glMask = 0;
4170     GLboolean      old_ztest;
4171     GLfloat        old_z_clear_value;
4172     GLint          old_stencil_clear_value;
4173     GLfloat        old_color_clear_value[4];
4174     unsigned int   i;
4175     CONST D3DRECT* curRect;
4176
4177     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4178           Count, pRects, Flags, Z, Stencil);
4179
4180     ENTER_GL();
4181
4182     glEnable(GL_SCISSOR_TEST);
4183     checkGLcall("glEnable GL_SCISSOR_TEST");
4184
4185     if (Count > 0 && pRects) {
4186         curRect = pRects;
4187     } else {
4188         curRect = NULL;
4189     }
4190
4191     /* Only set the values up once, as they are not changing */
4192     if (Flags & D3DCLEAR_STENCIL) {
4193         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4194         glClearStencil(Stencil);
4195         checkGLcall("glClearStencil");
4196         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4197         glStencilMask(0xFFFFFFFF);
4198     }
4199
4200     if (Flags & D3DCLEAR_ZBUFFER) {
4201         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4202         glDepthMask(GL_TRUE);
4203         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4204         glClearDepth(Z);
4205         checkGLcall("glClearDepth");
4206         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4207     }
4208
4209     if (Flags & D3DCLEAR_TARGET) {
4210         TRACE("Clearing screen with glClear to color %lx\n", Color);
4211         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4212         glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4213                      ((Color >>  8) & 0xFF) / 255.0f,
4214                      ((Color >>  0) & 0xFF) / 255.0f,
4215                      ((Color >> 24) & 0xFF) / 255.0f);
4216         checkGLcall("glClearColor");
4217
4218         /* Clear ALL colors! */
4219         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4220         glMask = glMask | GL_COLOR_BUFFER_BIT;
4221     }
4222
4223     /* Now process each rect in turn */
4224     for (i = 0; i < Count || i == 0; i++) {
4225
4226         if (curRect) {
4227             /* Note gl uses lower left, width/height */
4228             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4229                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4230                   curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4231                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4232             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4233                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4234             checkGLcall("glScissor");
4235         } else {
4236             glScissor(This->stateBlock->viewport.X,
4237                       (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - 
4238                       (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4239                       This->stateBlock->viewport.Width,
4240                       This->stateBlock->viewport.Height);
4241             checkGLcall("glScissor");
4242         }
4243
4244         /* Clear the selected rectangle (or full screen) */
4245         glClear(glMask);
4246         checkGLcall("glClear");
4247
4248         /* Step to the next rectangle */
4249         if (curRect) curRect = curRect + sizeof(D3DRECT);
4250     }
4251
4252     /* Restore the old values (why..?) */
4253     if (Flags & D3DCLEAR_STENCIL) {
4254         glClearStencil(old_stencil_clear_value);
4255         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4256     }
4257     if (Flags & D3DCLEAR_ZBUFFER) {
4258         glDepthMask(old_ztest);
4259         glClearDepth(old_z_clear_value);
4260     }
4261     if (Flags & D3DCLEAR_TARGET) {
4262         glClearColor(old_color_clear_value[0],
4263                      old_color_clear_value[1],
4264                      old_color_clear_value[2],
4265                      old_color_clear_value[3]);
4266         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4267                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4268                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4269                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4270     }
4271
4272     glDisable(GL_SCISSOR_TEST);
4273     checkGLcall("glDisable");
4274     LEAVE_GL();
4275
4276     return D3D_OK;
4277 }
4278
4279 /*****
4280  * Drawing functions
4281  *****/
4282 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4283                                                 UINT PrimitiveCount) {
4284
4285     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4286     This->stateBlock->streamIsUP = FALSE;
4287
4288     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4289                                debug_d3dprimitivetype(PrimitiveType),
4290                                StartVertex, PrimitiveCount);
4291     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4292                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4293
4294
4295     return D3D_OK;
4296 }
4297
4298 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4299 HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4300                                                            D3DPRIMITIVETYPE PrimitiveType,
4301                                                            INT baseVIndex, UINT minIndex,
4302                                                            UINT NumVertices, UINT startIndex, UINT primCount) {
4303
4304     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4305     UINT                 idxStride = 2;
4306     IWineD3DIndexBuffer *pIB;
4307     D3DINDEXBUFFER_DESC  IdxBufDsc;
4308
4309     pIB = This->stateBlock->pIndexData;
4310     This->stateBlock->streamIsUP = FALSE;
4311
4312     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4313           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4314           minIndex, NumVertices, startIndex, baseVIndex, primCount);
4315
4316     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4317     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4318         idxStride = 2;
4319     } else {
4320         idxStride = 4;
4321     }
4322
4323     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4324                    idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4325
4326     return D3D_OK;
4327 }
4328
4329 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4330                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4331                                                     UINT VertexStreamZeroStride) {
4332     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4333
4334     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4335              debug_d3dprimitivetype(PrimitiveType),
4336              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4337
4338     if (This->stateBlock->streamSource[0] != NULL) {
4339         IUnknown *vertexBufferParent;
4340         IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4341         IUnknown_Release(vertexBufferParent);
4342         IUnknown_Release(vertexBufferParent);
4343     }
4344
4345     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4346     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4347     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4348     This->stateBlock->streamIsUP = TRUE;
4349
4350     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4351                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4352     /* stream zero settings set to null at end, as per the msdn
4353             http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4354     */
4355     This->stateBlock->streamStride[0] = 0;
4356     This->stateBlock->streamSource[0] = NULL;
4357
4358     /*stream zero settings set to null at end, as per the msdn */
4359     return D3D_OK;
4360 }
4361
4362 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4363                                                              UINT MinVertexIndex, UINT NumVertices,
4364                                                              UINT PrimitiveCount, CONST void* pIndexData,
4365                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4366                                                              UINT VertexStreamZeroStride) {
4367     int                 idxStride;
4368     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4369
4370     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4371              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4372              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4373              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4374
4375     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4376         idxStride = 2;
4377     } else {
4378         idxStride = 4;
4379     }
4380
4381     if (This->stateBlock->streamSource[0] != NULL) {
4382         IUnknown *vertexBufferParent;
4383         IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4384         This->stateBlock->streamSource[0] = NULL;
4385         IUnknown_Release(vertexBufferParent);
4386         IUnknown_Release(vertexBufferParent);
4387     }
4388
4389     if (This->stateBlock->pIndexData) {
4390         IUnknown *indexBufferParent;
4391         IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4392         This->stateBlock->pIndexData = NULL;
4393         IUnknown_Release(indexBufferParent);
4394         IUnknown_Release(indexBufferParent);
4395     }
4396
4397     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4398     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4399     This->stateBlock->streamIsUP = TRUE;
4400     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4401
4402     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4403     /* stream zero settings set to null at end as per the msdn
4404     http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4405     */
4406
4407     /* stream zero settings set to null at end as per the msdn */
4408     This->stateBlock->streamSource[0] = NULL;
4409     This->stateBlock->streamStride[0] = 0;
4410
4411     return D3D_OK;
4412 }
4413
4414  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4415 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4416     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4417     D3DRESOURCETYPE sourceType;
4418     D3DRESOURCETYPE destinationType;
4419     IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4420     IWineD3DTextureImpl *pSrcTexture  = (IWineD3DTextureImpl *)pSourceTexture;
4421     int i;
4422
4423     sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4424     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4425     if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4426         FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4427         return D3DERR_INVALIDCALL;
4428     }
4429     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4430
4431     /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4432         repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4433         think about moving the code into texture, and adding a member to base texture to occomplish this **/
4434
4435     /* Make sure that the destination texture is loaded */
4436     IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4437     TRACE("Loading source texture\n");
4438
4439     if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4440         FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4441                pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4442     }
4443
4444     if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4445         ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4446
4447         FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4448         return D3DERR_INVALIDCALL;
4449     }
4450     /** TODO: check that both textures have the same number of levels  **/
4451 #if 0
4452     if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4453             return D3DERR_INVALIDCALL;
4454 #endif
4455     /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4456     for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4457         IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4458     }
4459
4460     return D3D_OK;
4461 }
4462
4463 HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4464                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4465                                                 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4466     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4467
4468     TRACE("(%p) : stub\n", This);
4469     return D3D_OK;
4470 }
4471 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4472     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4473
4474     TRACE("(%p) : stub\n", This);
4475     return D3D_OK;
4476 }
4477
4478 HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4479     IWineD3DSwapChain *swapChain;
4480     HRESULT hr;
4481     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4482     if(hr == D3D_OK) {
4483         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4484                 IWineD3DSwapChain_Release(swapChain);
4485     }
4486     return hr;
4487 }
4488
4489 HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4490     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4491     /* return a sensible default */
4492     *pNumPasses = 1;
4493     /* TODO: If the window is minimized then validate device shold return something other than d3d_ok */
4494     FIXME("(%p) : stub\n", This);
4495     return D3D_OK;
4496 }
4497
4498 HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4499     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4500     int j;
4501     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4502     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4503         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4504         return D3DERR_INVALIDCALL;
4505     }
4506     for (j = 0; j < 256; ++j) {
4507         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
4508         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4509         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
4510         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4511     }
4512     TRACE("(%p) : returning\n", This);
4513     return D3D_OK;
4514 }
4515
4516 HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4517     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4518     int j;
4519     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4520     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4521         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4522         return D3DERR_INVALIDCALL;
4523     }
4524     for (j = 0; j < 256; ++j) {
4525         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
4526         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4527         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
4528         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4529     }
4530     TRACE("(%p) : returning\n", This);
4531     return D3D_OK;
4532 }
4533
4534 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4535     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4536     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4537     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4538         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4539         return D3DERR_INVALIDCALL;
4540     }
4541     /*TODO: stateblocks */
4542     This->currentPalette = PaletteNumber;
4543     TRACE("(%p) : returning\n", This);
4544     return D3D_OK;
4545 }
4546
4547 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4548     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4549     if (PaletteNumber == NULL) {
4550         WARN("(%p) : returning Invalid Call\n", This);
4551         return D3DERR_INVALIDCALL;
4552     }
4553     /*TODO: stateblocks */
4554     *PaletteNumber = This->currentPalette;
4555     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
4556     return D3D_OK;
4557 }
4558
4559 HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4560     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4561     static BOOL showFixmes = TRUE;
4562     if (showFixmes) {
4563         FIXME("(%p) : stub\n", This);
4564         showFixmes = FALSE;
4565     }
4566
4567     This->updateStateBlock->softwareVertexProcessing = bSoftware;
4568     return D3D_OK;
4569 }
4570
4571
4572 BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4573     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4574     static BOOL showFixmes = TRUE;
4575     if (showFixmes) {
4576         FIXME("(%p) : stub\n", This);
4577         showFixmes = FALSE;
4578     }
4579     return This->updateStateBlock->softwareVertexProcessing;
4580 }
4581
4582
4583 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4584     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4585
4586     pRasterStatus->InVBlank = TRUE;
4587     pRasterStatus->ScanLine = 0;
4588     FIXME("(%p) : stub\n", This);
4589     return D3D_OK;
4590 }
4591
4592
4593 HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4594     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4595     static BOOL showfixmes = TRUE;
4596     if(nSegments != 0.0f) {
4597         if( showfixmes) {
4598             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4599             showfixmes = FALSE;
4600         }
4601     }
4602     return D3D_OK;
4603 }
4604
4605 float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4606     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4607     static BOOL showfixmes = TRUE;
4608     if( showfixmes) {
4609         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4610         showfixmes = FALSE;
4611     }
4612     return 0.0f;
4613 }
4614
4615
4616 HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4617     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
4618     /** TODO: remove casts to IWineD3DSurfaceImpl
4619      *       NOTE: move code to surface to accomplish this
4620       ****************************************/
4621     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
4622     int srcWidth, srcHeight;
4623     unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4624     WINED3DFORMAT destFormat, srcFormat;
4625     UINT destSize;
4626     int destLeft, destTop;
4627     D3DPOOL     srcPool, destPool;
4628     int offset    = 0;
4629     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4630     glDescriptor *glDescription = NULL;
4631     GLenum textureDimensions = GL_TEXTURE_2D;
4632     IWineD3DBaseTexture *baseTexture;
4633
4634     WINED3DSURFACE_DESC  winedesc;
4635
4636     memset(&winedesc, 0, sizeof(winedesc));
4637     winedesc.Width  = &srcSurfaceWidth;
4638     winedesc.Height = &srcSurfaceHeight;
4639     winedesc.Pool   = &srcPool;
4640     winedesc.Format = &srcFormat;
4641
4642     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4643
4644     winedesc.Width  = &destSurfaceWidth;
4645     winedesc.Height = &destSurfaceHeight;
4646     winedesc.Pool   = &destPool;
4647     winedesc.Format = &destFormat;
4648     winedesc.Size   = &destSize;
4649
4650     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4651
4652     if(srcPool != D3DPOOL_SYSTEMMEM  || destPool != D3DPOOL_DEFAULT){
4653         FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4654         return D3DERR_INVALIDCALL;
4655     }
4656     /* TODO:  change this to use bindTexture */
4657     /* Make sure the surface is loaded and upto date */
4658     IWineD3DSurface_PreLoad(pDestinationSurface);
4659
4660     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4661
4662     ENTER_GL();
4663
4664     /* this needs to be done in lines if the sourceRect != the sourceWidth */
4665     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
4666     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
4667     destLeft   = pDestPoint  ? pDestPoint->x : 0;
4668     destTop    = pDestPoint  ? pDestPoint->y : 0;
4669
4670
4671     /* This function doesn't support compressed textures
4672     the pitch is just bytesPerPixel * width */
4673
4674     if(srcWidth != srcSurfaceWidth  || (pSourceRect != NULL && pSourceRect->left != 0) ){
4675         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4676         offset   += pSourceRect->left * pSrcSurface->bytesPerPixel;
4677         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4678     }
4679     /* TODO DXT formats */
4680
4681     if(pSourceRect != NULL && pSourceRect->top != 0){
4682        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4683     }
4684     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4685     ,This
4686     ,glDescription->level
4687     ,destLeft
4688     ,destTop
4689     ,srcWidth
4690     ,srcHeight
4691     ,glDescription->glFormat
4692     ,glDescription->glType
4693     ,IWineD3DSurface_GetData(pSourceSurface)
4694     );
4695
4696     /* Sanity check */
4697     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4698     /* need to lock the surface to get the data */
4699        FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4700     }
4701     /* TODO: Cube and volume support */
4702     if(rowoffset != 0){
4703         /* not a whole row so we have to do it a line at a time */
4704         int j;
4705         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4706         unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4707
4708         for(j = destTop ; j < (srcHeight + destTop) ; j++){
4709
4710                 glTexSubImage2D(glDescription->target
4711                     ,glDescription->level
4712                     ,destLeft
4713                     ,j
4714                     ,srcWidth
4715                     ,1
4716                     ,glDescription->glFormat
4717                     ,glDescription->glType
4718                     ,data/* could be quicker using */
4719                 );
4720             data += rowoffset;
4721         }
4722
4723     } else { /* Full width, so just write out the whole texture */
4724
4725         if (WINED3DFMT_DXT1 == destFormat ||
4726             WINED3DFMT_DXT3 == destFormat ||
4727             WINED3DFMT_DXT5 == destFormat) {
4728             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4729                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4730                     /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4731                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
4732                 } if (destFormat != srcFormat) {
4733                     FIXME("Updating mixed format compressed texture is not curretly support\n");
4734                 } else {
4735                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4736                                                         glDescription->level,
4737                                                         glDescription->glFormatInternal,
4738                                                         srcWidth,
4739                                                         srcHeight,
4740                                                         0,
4741                                                         destSize,
4742                                                         IWineD3DSurface_GetData(pSourceSurface));
4743                 }
4744             } else {
4745                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4746             }
4747
4748
4749         } else {
4750             /* some applications cannot handle odd pitches returned by soft non-power2, so we have
4751                to repack the data from pow2Width/Height to expected Width,Height, this makes the
4752                data returned by GetData non-power2 width/height with hardware non-power2
4753                pow2Width/height are set to surface width height, repacking isn't needed so it
4754                doesn't matter which function gets called. */
4755             glTexSubImage2D(glDescription->target
4756                     ,glDescription->level
4757                     ,destLeft
4758                     ,destTop
4759                     ,srcWidth
4760                     ,srcHeight
4761                     ,glDescription->glFormat
4762                     ,glDescription->glType
4763                     ,IWineD3DSurface_GetData(pSourceSurface)
4764                 );
4765
4766         }
4767      }
4768     checkGLcall("glTexSubImage2D");
4769     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4770      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4771      * surface bigger than it needs to be hmm.. */
4772     if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
4773         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
4774         IWineD3DBaseTexture_Release(baseTexture);
4775     }
4776
4777     glDisable(textureDimensions); /* This needs to be managed better.... */
4778     LEAVE_GL();
4779
4780     return D3D_OK;
4781 }
4782
4783 /* Implementation details at http://developer.nvidia.com/attach/6494
4784 and
4785 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4786 hmm.. no longer supported use
4787 OpenGL evaluators or  tessellate surfaces within your application.
4788 */
4789
4790 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4791 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4792     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4793     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4794     FIXME("(%p) : Stub\n", This);
4795     return D3D_OK;
4796
4797 }
4798
4799 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4800 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4801     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4802     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4803     FIXME("(%p) : Stub\n", This);
4804     return D3D_OK;
4805 }
4806
4807 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4808     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4809     TRACE("(%p) Handle(%d)\n", This, Handle);
4810     FIXME("(%p) : Stub\n", This);
4811     return D3D_OK;
4812 }
4813
4814 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
4815     /* I couldn't find a 'really' quick way of doing this in openGl so here goes
4816     fill a surface with a block of color!  */
4817     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4818     /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
4819     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
4820     IWineD3DSwapChainImpl *container = NULL;
4821     BOOL isRenderTarget = FALSE;
4822     unsigned int width, height;
4823     unsigned int top, left;
4824     unsigned int u, v;
4825     DWORD       *data;
4826     TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
4827
4828     if (surface->resource.pool != D3DPOOL_DEFAULT) {
4829         FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
4830         return D3DERR_INVALIDCALL;
4831     }
4832
4833     /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
4834     if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
4835         if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
4836             /* TODO: make sure we set everything back to the way it was, and context management!
4837                 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4838                 vcheckGLcall("glIntegerv");
4839                 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
4840                 vcheckGLcall("glIntegerv");
4841             */
4842             TRACE("Color fill to render targets may cause some graphics issues\n");
4843             if (pSurface == container->frontBuffer) {
4844                 glDrawBuffer(GL_FRONT);
4845             } else {
4846                 glDrawBuffer(GL_BACK);
4847             }
4848         } else {
4849             if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
4850                 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
4851             } else {
4852                 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
4853             }
4854             if (container != NULL) {
4855                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4856             }
4857             /* we can use GL_STENCIL_INDEX etc...*/
4858             return D3D_OK;
4859         }
4860         if (container != NULL) {
4861             IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
4862         }
4863         isRenderTarget = TRUE;
4864     }
4865     /* TODO: drawing to GL_FRONT and GL_BACK */
4866     /* TODO: see if things can be speeded up by using the correct
4867      * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
4868     if (pRect == NULL) {
4869         top    = 0;
4870         left   = 0;
4871         width  = surface->currentDesc.Width;
4872         height = surface->currentDesc.Height;
4873     } else {
4874         left   = pRect->x1;
4875         top    = pRect->y1;
4876         width  = pRect->x2 - left;
4877         height = pRect->y2 - top;
4878     }
4879
4880     data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
4881     /* Create a 'line' of color color, in the correct format for the surface */
4882     for (u = 0 ; u < width ; u ++) {
4883             data[u] = color;
4884     }
4885
4886     ENTER_GL();
4887     if (isRenderTarget == FALSE) {
4888         glDescriptor *glDesc;
4889         IWineD3DSurface_PreLoad(pSurface);
4890
4891         /* draw a block of the coloured line on the sufrace */
4892         IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
4893         for (v = 0 ; v< height;v++) {
4894             glTexSubImage2D(glDesc->target
4895                             ,glDesc->level /* level */
4896                             ,left
4897                             ,top + v
4898                             ,width
4899                             ,1 /* height */
4900                             ,GL_RGBA
4901                             ,GL_UNSIGNED_BYTE
4902                             ,data
4903                             );
4904         }
4905         checkGLcall("glTexSubImage2D");
4906         /* clean up */
4907         glDisable(glDesc->target);
4908     } else {
4909         /** FIXME: Using GLClear may be faster **/
4910         glRasterPos2i(left, top);
4911         glPixelZoom((float)width ,(float)height);
4912         glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
4913         checkGLcall("glDrawPixels");
4914     }
4915     HeapFree(GetProcessHeap(), 0, data);
4916     LEAVE_GL();
4917     return D3D_OK;
4918
4919 }
4920
4921 /* rendertarget and deptth stencil functions */
4922 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4923     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4924
4925     /* FIXME: Implelent RenderTargetIndex >0 */
4926     if(RenderTargetIndex > 0)
4927         FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4928
4929     *ppRenderTarget = This->renderTarget;
4930     TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4931     /* Note inc ref on returned surface */
4932     if(*ppRenderTarget != NULL)
4933         IWineD3DSurface_AddRef(*ppRenderTarget);
4934     return D3D_OK;
4935 }
4936
4937 HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
4938     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4939     *ppZStencilSurface = This->depthStencilBuffer;
4940     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
4941
4942     if(*ppZStencilSurface != NULL) {
4943         /* Note inc ref on returned surface */
4944         IWineD3DSurface_AddRef(*ppZStencilSurface);
4945     }
4946     return D3D_OK;
4947 }
4948
4949 /* internal static helper functions */
4950 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4951                                                 IWineD3DSurface *RenderSurface);
4952
4953 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
4954
4955 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
4956
4957 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
4958     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4959     HRESULT  hr = D3D_OK;
4960     WINED3DVIEWPORT viewport;
4961
4962     TRACE("(%p) Swapping rendertarget\n",This);
4963     if (RenderTargetIndex > 0) {
4964         FIXME("(%p) Render targets other than the first are not supported\n",This);
4965         RenderTargetIndex = 0;
4966     }
4967
4968     /* MSDN says that null disables the render target
4969     but a device must always be associated with a render target
4970     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
4971
4972     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
4973     for more details
4974     */
4975     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
4976         FIXME("Trying to set render target 0 to NULL\n");
4977         return D3DERR_INVALIDCALL;
4978     }
4979     /* TODO: replace Impl* usage with interface usage */
4980     if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
4981         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);
4982         return D3DERR_INVALIDCALL;
4983     }
4984     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
4985      *        builds, but I think wine counts as a 'debug' build for now.
4986       ******************************/
4987     /* If we are trying to set what we already have, don't bother */
4988     if (pRenderTarget == This->renderTarget) {
4989         TRACE("Trying to do a NOP SetRenderTarget operation\n");
4990     } else {
4991         /* Otherwise, set the render target up */
4992
4993         if (FALSE == This->sceneEnded) {
4994             IWineD3DDevice_EndScene(iface);
4995         }
4996         TRACE("clearing renderer\n");
4997         /* IWineD3DDeviceImpl_CleanRender(iface); */
4998         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4999         depending on the renter target implementation being used.
5000         A shared context implementation will share all buffers between all rendertargets (including swapchains),
5001         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5002         stencil buffer and incure an extra memory overhead */
5003         hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5004     }
5005
5006     if (SUCCEEDED(hr)) {
5007         /* Finally, reset the viewport as the MSDN states. */
5008         /* TODO: Replace impl usage */
5009         viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5010         viewport.Width  = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5011         viewport.X      = 0;
5012         viewport.Y      = 0;
5013         viewport.MaxZ   = 1.0f;
5014         viewport.MinZ   = 0.0f;
5015         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5016     } else {
5017         FIXME("Unknown error setting the render target\n");
5018     }
5019     This->sceneEnded = FALSE;
5020     return hr;
5021 }
5022
5023 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5024     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5025     HRESULT  hr = D3D_OK;
5026     IWineD3DSurface *tmp;
5027
5028     TRACE("(%p) Swapping z-buffer\n",This);
5029
5030     if (pNewZStencil == This->stencilBufferTarget) {
5031         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5032     } else {
5033         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5034         * depending on the renter target implementation being used.
5035         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5036         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5037         * stencil buffer and incure an extra memory overhead
5038          ******************************************************/
5039
5040
5041         tmp = This->stencilBufferTarget;
5042         This->stencilBufferTarget = pNewZStencil;
5043         /* should we be calling the parent or the wined3d surface? */
5044         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5045         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5046         hr = D3D_OK;
5047         /** TODO: glEnable/glDisable on depth/stencil    depending on
5048          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
5049           **********************************************************/
5050     }
5051
5052     return hr;
5053 }
5054
5055
5056 /* Internal functions not in DirectX */
5057  /** TODO: move this off to the opengl context manager
5058  *(the swapchain doesn't need to know anything about offscreen rendering!)
5059   ****************************************************/
5060
5061 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5062 {
5063     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5064
5065     TRACE("(%p), %p\n", This, swapchain);
5066
5067     if (swapchain->win != swapchain->drawable) {
5068         /* Set everything back the way it ws */
5069         swapchain->render_ctx = swapchain->glCtx;
5070         swapchain->drawable   = swapchain->win;
5071     }
5072     return D3D_OK;
5073 }
5074
5075 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5076 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5077     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5078     int i;
5079     unsigned int width;
5080     unsigned int height;
5081     WINED3DFORMAT format;
5082     WINED3DSURFACE_DESC surfaceDesc;
5083     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5084     surfaceDesc.Width  = &width;
5085     surfaceDesc.Height = &height;
5086     surfaceDesc.Format = &format;
5087     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5088     *context = NULL;
5089     /* I need a get width/height function (and should do something with the format) */
5090     for (i = 0; i < CONTEXT_CACHE; ++i) {
5091         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5092         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5093         the pSurface can be set to 0 allowing it to be reused from cache **/
5094         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5095           && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5096             *context = &This->contextCache[i];
5097             break;
5098         }
5099         if (This->contextCache[i].Width == 0) {
5100             This->contextCache[i].pSurface = pSurface;
5101             This->contextCache[i].Width    = width;
5102             This->contextCache[i].Height   = height;
5103             *context = &This->contextCache[i];
5104             break;
5105         }
5106     }
5107     if (i == CONTEXT_CACHE) {
5108         int minUsage = 0x7FFFFFFF; /* MAX_INT */
5109         glContext *dropContext = 0;
5110         for (i = 0; i < CONTEXT_CACHE; i++) {
5111             if (This->contextCache[i].usedcount < minUsage) {
5112                 dropContext = &This->contextCache[i];
5113                 minUsage = This->contextCache[i].usedcount;
5114             }
5115         }
5116         /* clean up the context (this doesn't work for ATI at the moment */
5117 #if 0
5118         glXDestroyContext(swapchain->display, dropContext->context);
5119         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5120 #endif
5121         FIXME("Leak\n");
5122         dropContext->Width = 0;
5123         dropContext->pSurface = pSurface;
5124         *context = dropContext;
5125     } else {
5126         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5127           for (i = 0; i < CONTEXT_CACHE; i++) {
5128              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5129           }
5130         }
5131     }
5132     if (*context != NULL)
5133         return D3D_OK;
5134     else
5135         return E_OUTOFMEMORY;
5136 }
5137
5138 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5139 * the functionality needs splitting up so that we don't do more than we should do.
5140 * this only seems to impact performance a little.
5141  ******************************/
5142 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5143                                                IWineD3DSurface *RenderSurface) {
5144     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5145
5146     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5147     HRESULT ret =  D3DERR_INVALIDCALL;
5148     IWineD3DSurface *tmp;
5149     /**
5150     * Currently only active for GLX >= 1.3
5151     * for others versions we'll have to use GLXPixmaps
5152     *
5153     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5154     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5155     * so only check OpenGL version
5156     * ..........................
5157     * I don't believe that it is a problem with NVidia headers,
5158     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5159     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5160     * ATI Note:
5161     * Your application will report GLX version 1.2 on glXQueryVersion.
5162     * However, it is safe to call the GLX 1.3 functions as described below.
5163     */
5164 #if defined(GL_VERSION_1_3)
5165
5166     /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5167     GLXFBConfig* cfgs = NULL;
5168     int nCfgs = 0;
5169     int attribs[256];
5170     int nAttribs = 0;
5171     IWineD3DSwapChain     *currentSwapchain;
5172     IWineD3DSwapChainImpl *swapchain;
5173     /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5174     * but switch them off if the StencilSurface is set to NULL
5175     ** *********************************************************/
5176     D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5177     D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5178
5179     /**TODO:
5180         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5181         it StencilSurface != NULL && zBufferTarget == NULL switch it on
5182     */
5183
5184 #define PUSH1(att)        attribs[nAttribs++] = (att);
5185 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5186
5187     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5188
5189     /** TODO: remove the reff to Impl (context manager should fix this!) **/
5190     IWineD3DSwapChainImpl *impSwapChain;
5191     IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5192     if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5193         ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5194     }
5195
5196     ENTER_GL();
5197
5198     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5199     PUSH2(GLX_X_RENDERABLE,  TRUE);
5200     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
5201     TRACE("calling makeglcfg\n");
5202     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5203     PUSH1(None);
5204
5205     TRACE("calling chooseFGConfig\n");
5206     cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5207                                                      attribs, &nCfgs);
5208
5209     if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5210         /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5211            why we failed and only show this message once! */
5212         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"); /**/
5213         nAttribs = 0;
5214         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5215        /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
5216         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
5217         PUSH2(GLX_DOUBLEBUFFER, FALSE);
5218         TRACE("calling makeglcfg\n");
5219         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5220         PUSH1(None);
5221         cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5222                                                         attribs, &nCfgs);
5223     }
5224
5225     if (NULL != cfgs) {
5226 #ifdef EXTRA_TRACES
5227         int i;
5228         for (i = 0; i < nCfgs; ++i) {
5229             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5230             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5231             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5232         }
5233
5234         if (NULL != This->renderTarget) {
5235             glFlush();
5236             vcheckGLcall("glFlush");
5237             /** This is only useful if the old render target was a swapchain,
5238             * we need to supercede this with a function that displays
5239             * the current buffer on the screen. This is easy to do in glx1.3 but
5240             * we need to do copy-write pixels in glx 1.2.
5241             ************************************************/
5242             glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5243
5244             printf("Hit Enter to get next frame ...\n");
5245             getchar();
5246         }
5247 #endif
5248     }
5249
5250     if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK) {
5251         /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5252         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
5253     }
5254
5255     /**
5256     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5257     *  renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5258      **********************************************************************/
5259     if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5260         /* We also need to make sure that the lights &co are also in the context of the swapchains */
5261         /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5262         TRACE("making swapchain active\n");
5263         if (RenderSurface != This->renderTarget) {
5264             if (RenderSurface ==  swapchain->backBuffer) {
5265             } else {
5266                 /* This could be flagged so that some operations work directly with the front buffer */
5267                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
5268             }
5269             if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5270             == False) {
5271                 TRACE("Error in setting current context: context %p drawable %ld !\n",
5272                        impSwapChain->glCtx, impSwapChain->win);
5273             }
5274
5275             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5276         }
5277         checkGLcall("glXMakeContextCurrent");
5278
5279         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5280     }
5281     else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5282
5283         /** ********************************************************************
5284         * This is a quickly hacked out implementation of offscreen textures.
5285         * It will work in most cases but there may be problems if the client
5286         * modifies the texture directly, or expects the contents of the rendertarget
5287         * to be persistent.
5288         *
5289         * There are some real speed vs compatibility issues here:
5290         *    we should really use a new context for every texture, but that eats ram.
5291         *    we should also be restoring the texture to the pbuffer but that eats CPU
5292         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5293         *    but if this means reusing the display backbuffer then we need to make sure that
5294         *    states are correctly preserved.
5295         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5296         * and gain a good performance increase at the cost of compatibility.
5297         * I would suggest that, when this is the case, a user configurable flag be made
5298         * available, allowing the user to choose the best emulated experience for them.
5299          *********************************************************************/
5300
5301         XVisualInfo *visinfo;
5302         glContext   *newContext;
5303
5304         /* Here were using a shared context model */
5305         if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5306             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5307         }
5308
5309         /* If the context doesn't exist then create a new one */
5310         /* TODO: This should really be part of findGlContext */
5311         if (NULL == newContext->context) {
5312
5313             TRACE("making new buffer\n");
5314             nAttribs = 0;
5315             PUSH2(GLX_PBUFFER_WIDTH,  newContext->Width);
5316             PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5317             PUSH1(None);
5318
5319             newContext->drawable  = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5320
5321             /** ****************************************
5322             *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5323             *they note:
5324             *   In future releases, we may provide the calls glXCreateNewContext,
5325             *   glXQueryDrawable and glXMakeContextCurrent.
5326             *    so until then we have to use glXGetVisualFromFBConfig &co..
5327             ********************************************/
5328
5329
5330             visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5331             if (!visinfo) {
5332                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5333             } else {
5334                 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx,  GL_TRUE);
5335                 XFree(visinfo);
5336             }
5337         }
5338         if (NULL == newContext || NULL == newContext->context) {
5339             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5340         } else {
5341             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5342             if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5343                 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5344             }
5345
5346             /* Clean up the old context */
5347             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5348             /* Set the current context of the swapchain to the new context */
5349             impSwapChain->drawable   = newContext->drawable;
5350             impSwapChain->render_ctx = newContext->context;
5351         }
5352     }
5353
5354 #if 1 /* Apply the stateblock to the new context
5355 FIXME: This is a bit of a hack, each context should know it's own state,
5356 the directX current directX state should then be applied to the context */
5357     {
5358         BOOL oldRecording;
5359         IWineD3DStateBlockImpl *oldUpdateStateBlock;
5360         oldUpdateStateBlock = This->updateStateBlock;
5361         oldRecording= This->isRecordingState;
5362         This->isRecordingState = FALSE;
5363         This->updateStateBlock = This->stateBlock;
5364         IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5365
5366         This->isRecordingState = oldRecording;
5367         This->updateStateBlock = oldUpdateStateBlock;
5368     }
5369 #endif
5370
5371
5372     /* clean up the current rendertargets swapchain (if it belonged to one) */
5373     if (currentSwapchain != NULL) {
5374         IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5375     }
5376
5377     /* Were done with the opengl context management, setup the rendertargets */
5378
5379     tmp = This->renderTarget;
5380     This->renderTarget = RenderSurface;
5381     IWineD3DSurface_AddRef(This->renderTarget);
5382     IWineD3DSurface_Release(tmp);
5383
5384
5385
5386     {
5387         DWORD value;
5388         /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5389         /* Check that the container is not a swapchain member */
5390
5391         IWineD3DSwapChain *tmpSwapChain;
5392         if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5393             This->renderUpsideDown = TRUE;
5394         }else{
5395             This->renderUpsideDown = FALSE;
5396             IWineD3DSwapChain_Release(tmpSwapChain);
5397         }
5398         /* Force updating the cull mode */
5399         TRACE("setting render state\n");
5400         IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5401         IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5402
5403         /* Force updating projection matrix */
5404         This->last_was_rhw = FALSE;
5405         This->proj_valid = FALSE;
5406     }
5407
5408     ret = D3D_OK;
5409
5410     if (cfgs != NULL) {
5411         XFree(cfgs);
5412     } else {
5413         ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5414             debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5415     }
5416
5417 #undef PUSH1
5418 #undef PUSH2
5419     if ( NULL != impSwapChain) {
5420         IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5421     }
5422     LEAVE_GL();
5423
5424 #endif
5425     return ret;
5426 }
5427
5428 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5429                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5430     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5431     /* TODO: the use of Impl is deprecated. */
5432     /* some basic validation checks */
5433     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5434
5435     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5436
5437     if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5438       ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5439       return D3DERR_INVALIDCALL;
5440     }
5441     if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5442       ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5443       return D3DERR_INVALIDCALL;
5444     }
5445     /* TODO: make the cursor 'real' */
5446
5447     This->xHotSpot = XHotSpot;
5448     This->yHotSpot = YHotSpot;
5449
5450     return D3D_OK;
5451 }
5452
5453 void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5454     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5455     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5456
5457     This->xScreenSpace = XScreenSpace;
5458     This->yScreenSpace = YScreenSpace;
5459
5460     return;
5461
5462 }
5463
5464 BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5465     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5466     TRACE("(%p) : visible(%d)\n", This, bShow);
5467
5468     This->bCursorVisible = bShow;
5469
5470     return D3D_OK;
5471 }
5472
5473 HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5474     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5475     FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5476     return D3D_OK;
5477 }
5478
5479
5480 HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5481     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5482     /** FIXME: Resource tracking needs to be done,
5483     * The closes we can do to this is set the priorities of all managed textures low
5484     * and then reset them.
5485      ***********************************************************/
5486     FIXME("(%p) : stub\n", This);
5487     return D3D_OK;
5488 }
5489
5490 HRESULT  WINAPI  IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5491     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5492     /** FIXME: Resource trascking needs to be done.
5493     * in effect this pulls all non only default
5494     * textures out of video memory and deletes all glTextures (glDeleteTextures)
5495     * and should clear down the context and set it up according to pPresentationParameters
5496      ***********************************************************/
5497     FIXME("(%p) : stub\n", This);
5498     return D3D_OK;
5499 }
5500
5501 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5502     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5503     /** FIXME: always true at the moment **/
5504     if(bEnableDialogs == FALSE) {
5505         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5506     }
5507     return D3D_OK;
5508 }
5509
5510
5511 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5512     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5513
5514     FIXME("(%p) : stub\n", This);
5515     /* Setup some reasonable defaults */
5516     pParameters->AdapterOrdinal = 0; /* always for now */
5517     pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5518     pParameters->hFocusWindow = 0;
5519     pParameters->BehaviorFlags =0;
5520     return D3D_OK;
5521 }
5522
5523 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5524     IWineD3DSwapChain *swapchain;
5525     HRESULT hrc = D3D_OK;
5526
5527     TRACE("Relaying  to swapchain\n");
5528
5529     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5530         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5531         IWineD3DSwapChain_Release(swapchain);
5532     }
5533     return;
5534 }
5535
5536 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5537     IWineD3DSwapChain *swapchain;
5538     HRESULT hrc = D3D_OK;
5539
5540     TRACE("Relaying  to swapchain\n");
5541
5542     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5543         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5544         IWineD3DSwapChain_Release(swapchain);
5545     }
5546     return;
5547 }
5548
5549
5550 /** ********************************************************
5551 *   Notification functions
5552 ** ********************************************************/
5553 /** This function must be called in the release of a resource when ref == 0,
5554 * the contents of resource must still be correct,
5555 * any handels to other resource held by the caller must be closed
5556 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5557  *****************************************************/
5558 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5559     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5560     ResourceList* resourceList;
5561
5562     TRACE("(%p) : resource %p\n", This, resource);
5563 #if 0
5564     EnterCriticalSection(&resourceStoreCriticalSection);
5565 #endif
5566     /* add a new texture to the frot of the linked list */
5567     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5568     resourceList->resource = resource;
5569
5570     /* Get the old head */
5571     resourceList->next = This->resources;
5572
5573     This->resources = resourceList;
5574     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5575
5576 #if 0
5577     LeaveCriticalSection(&resourceStoreCriticalSection);
5578 #endif
5579     return;
5580 }
5581
5582 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5583     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5584     ResourceList* resourceList = NULL;
5585     ResourceList* previousResourceList = NULL;
5586     
5587     TRACE("(%p) : resource %p\n", This, resource);
5588
5589 #if 0
5590     EnterCriticalSection(&resourceStoreCriticalSection);
5591 #endif
5592     resourceList = This->resources;
5593
5594     while (resourceList != NULL) {
5595         if(resourceList->resource == resource) break;
5596         previousResourceList = resourceList;
5597         resourceList = resourceList->next;
5598     }
5599
5600     if (resourceList == NULL) {
5601         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5602 #if 0
5603         LeaveCriticalSection(&resourceStoreCriticalSection);
5604 #endif
5605         return;
5606     } else {
5607             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5608     }
5609     /* make sure we don't leave a hole in the list */
5610     if (previousResourceList != NULL) {
5611         previousResourceList->next = resourceList->next;
5612     } else {
5613         This->resources = resourceList->next;
5614     }
5615
5616 #if 0
5617     LeaveCriticalSection(&resourceStoreCriticalSection);
5618 #endif
5619     return;
5620 }
5621
5622
5623 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5624     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5625     int counter;
5626
5627     TRACE("(%p) : resource %p\n", This, resource);
5628     switch(IWineD3DResource_GetType(resource)){
5629         case D3DRTYPE_SURFACE:
5630         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
5631         break;
5632         case D3DRTYPE_TEXTURE:
5633         case D3DRTYPE_CUBETEXTURE:
5634         case D3DRTYPE_VOLUMETEXTURE:
5635                 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5636                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5637                         IUnknown *textureParent;
5638                         IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5639                         /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5640                         FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5641                         IUnknown_Release(textureParent);
5642                         This->stateBlock->textures[counter] = NULL;
5643                     }
5644                     if (This->updateStateBlock != This->stateBlock ){
5645                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5646                             IUnknown *textureParent;
5647                             IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5648                             /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5649                             FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5650                             IUnknown_Release(textureParent);
5651                             This->updateStateBlock->textures[counter] = NULL;
5652                         }
5653                     }
5654                 }
5655         break;
5656         case D3DRTYPE_VOLUME:
5657         /* TODO: nothing really? */
5658         break;
5659         case D3DRTYPE_VERTEXBUFFER:
5660         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5661         {
5662             int streamNumber;
5663             TRACE("Cleaning up stream pointers\n");
5664
5665             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5666                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5667                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5668                 */
5669                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5670                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5671                         FIXME("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
5672                         This->updateStateBlock->streamSource[streamNumber] = 0;
5673                         /* Set changed flag? */
5674                     }
5675                 }
5676                 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) */
5677                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5678                         TRACE("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
5679                         This->stateBlock->streamSource[streamNumber] = 0;
5680                     }
5681                 }
5682 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5683                  else { /* This shouldn't happen */
5684                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5685                 }
5686 #endif
5687
5688             }
5689         }
5690         break;
5691         case D3DRTYPE_INDEXBUFFER:
5692         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5693         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5694             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5695                 This->updateStateBlock->pIndexData =  NULL;
5696             }
5697         }
5698         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5699             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5700                 This->stateBlock->pIndexData =  NULL;
5701             }
5702         }
5703
5704         break;
5705         default:
5706         FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5707         break;
5708     }
5709
5710
5711     /* Remove the resoruce from the resourceStore */
5712     IWineD3DDeviceImpl_RemoveResource(iface, resource);
5713
5714     TRACE("Resource released\n");
5715
5716 }
5717
5718
5719 /** This function is to be called by the swapchain when it is released and it's ref = 0
5720  *****************************************************/
5721 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5722     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5723     SwapChainList **nextSwapchain;
5724     nextSwapchain = &This->swapchains;
5725
5726     /* Check to see if the swapchian is being used as the render target */
5727     if (This->renderTarget != NULL) {
5728         IWineD3DSurface *swapchainBackBuffer;
5729
5730         IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5731         if (This->renderTarget == swapchainBackBuffer) {
5732             /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5733             FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5734         }
5735     }
5736
5737     /* Go through the swapchain list and try to find the swapchain being released */
5738     while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
5739         nextSwapchain = &(*nextSwapchain)->next;
5740     }
5741
5742     /* Check to see if we found the swapchain */
5743     if (NULL != *nextSwapchain) {
5744         /* We found the swapchain so remove it from the list */
5745         TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
5746         HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
5747         *nextSwapchain = (*nextSwapchain)->next;
5748     } else {
5749         /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
5750         FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
5751     }
5752
5753     TRACE("swapchain (%p) released\n", swapChain);
5754     return;
5755 }
5756
5757 /**********************************************************
5758  * IWineD3DDevice VTbl follows
5759  **********************************************************/
5760
5761 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5762 {
5763     /*** IUnknown methods ***/
5764     IWineD3DDeviceImpl_QueryInterface,
5765     IWineD3DDeviceImpl_AddRef,
5766     IWineD3DDeviceImpl_Release,
5767     /*** IWineD3DDevice methods ***/
5768     IWineD3DDeviceImpl_GetParent,
5769     /*** Creation methods**/
5770     IWineD3DDeviceImpl_CreateVertexBuffer,
5771     IWineD3DDeviceImpl_CreateIndexBuffer,
5772     IWineD3DDeviceImpl_CreateStateBlock,
5773     IWineD3DDeviceImpl_CreateSurface,
5774     IWineD3DDeviceImpl_CreateTexture,
5775     IWineD3DDeviceImpl_CreateVolumeTexture,
5776     IWineD3DDeviceImpl_CreateVolume,
5777     IWineD3DDeviceImpl_CreateCubeTexture,
5778     IWineD3DDeviceImpl_CreateQuery,
5779     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5780     IWineD3DDeviceImpl_CreateVertexDeclaration,
5781     IWineD3DDeviceImpl_CreateVertexShader,
5782     IWineD3DDeviceImpl_CreatePixelShader,
5783     /*** Odd functions **/
5784     IWineD3DDeviceImpl_EvictManagedResources,
5785     IWineD3DDeviceImpl_GetAvailableTextureMem,
5786     IWineD3DDeviceImpl_GetBackBuffer,
5787     IWineD3DDeviceImpl_GetCreationParameters,
5788     IWineD3DDeviceImpl_GetDeviceCaps,
5789     IWineD3DDeviceImpl_GetDirect3D,
5790     IWineD3DDeviceImpl_GetDisplayMode,
5791     IWineD3DDeviceImpl_GetNumberOfSwapChains,
5792     IWineD3DDeviceImpl_GetRasterStatus,
5793     IWineD3DDeviceImpl_GetSwapChain,
5794     IWineD3DDeviceImpl_Reset,
5795     IWineD3DDeviceImpl_SetDialogBoxMode,
5796     IWineD3DDeviceImpl_SetCursorProperties,
5797     IWineD3DDeviceImpl_SetCursorPosition,
5798     IWineD3DDeviceImpl_ShowCursor,
5799     IWineD3DDeviceImpl_TestCooperativeLevel,
5800     /*** Getters and setters **/
5801     IWineD3DDeviceImpl_SetClipPlane,
5802     IWineD3DDeviceImpl_GetClipPlane,
5803     IWineD3DDeviceImpl_SetClipStatus,
5804     IWineD3DDeviceImpl_GetClipStatus,
5805     IWineD3DDeviceImpl_SetCurrentTexturePalette,
5806     IWineD3DDeviceImpl_GetCurrentTexturePalette,
5807     IWineD3DDeviceImpl_SetDepthStencilSurface,
5808     IWineD3DDeviceImpl_GetDepthStencilSurface,
5809     IWineD3DDeviceImpl_SetFVF,
5810     IWineD3DDeviceImpl_GetFVF,
5811     IWineD3DDeviceImpl_SetGammaRamp,
5812     IWineD3DDeviceImpl_GetGammaRamp,
5813     IWineD3DDeviceImpl_SetIndices,
5814     IWineD3DDeviceImpl_GetIndices,
5815     IWineD3DDeviceImpl_SetLight,
5816     IWineD3DDeviceImpl_GetLight,
5817     IWineD3DDeviceImpl_SetLightEnable,
5818     IWineD3DDeviceImpl_GetLightEnable,
5819     IWineD3DDeviceImpl_SetMaterial,
5820     IWineD3DDeviceImpl_GetMaterial,
5821     IWineD3DDeviceImpl_SetNPatchMode,
5822     IWineD3DDeviceImpl_GetNPatchMode,
5823     IWineD3DDeviceImpl_SetPaletteEntries,
5824     IWineD3DDeviceImpl_GetPaletteEntries,
5825     IWineD3DDeviceImpl_SetPixelShader,
5826     IWineD3DDeviceImpl_GetPixelShader,
5827     IWineD3DDeviceImpl_SetPixelShaderConstantB,
5828     IWineD3DDeviceImpl_GetPixelShaderConstantB,
5829     IWineD3DDeviceImpl_SetPixelShaderConstantI,
5830     IWineD3DDeviceImpl_GetPixelShaderConstantI,
5831     IWineD3DDeviceImpl_SetPixelShaderConstantF,
5832     IWineD3DDeviceImpl_GetPixelShaderConstantF,
5833     IWineD3DDeviceImpl_SetRenderState,
5834     IWineD3DDeviceImpl_GetRenderState,
5835     IWineD3DDeviceImpl_SetRenderTarget,
5836     IWineD3DDeviceImpl_GetRenderTarget,
5837     IWineD3DDeviceImpl_SetSamplerState,
5838     IWineD3DDeviceImpl_GetSamplerState,
5839     IWineD3DDeviceImpl_SetScissorRect,
5840     IWineD3DDeviceImpl_GetScissorRect,
5841     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5842     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5843     IWineD3DDeviceImpl_SetStreamSource,
5844     IWineD3DDeviceImpl_GetStreamSource,
5845     IWineD3DDeviceImpl_SetStreamSourceFreq,
5846     IWineD3DDeviceImpl_GetStreamSourceFreq,
5847     IWineD3DDeviceImpl_SetTexture,
5848     IWineD3DDeviceImpl_GetTexture,
5849     IWineD3DDeviceImpl_SetTextureStageState,
5850     IWineD3DDeviceImpl_GetTextureStageState,
5851     IWineD3DDeviceImpl_SetTransform,
5852     IWineD3DDeviceImpl_GetTransform,
5853     IWineD3DDeviceImpl_SetVertexDeclaration,
5854     IWineD3DDeviceImpl_GetVertexDeclaration,
5855     IWineD3DDeviceImpl_SetVertexShader,
5856     IWineD3DDeviceImpl_GetVertexShader,
5857     IWineD3DDeviceImpl_SetVertexShaderConstantB,
5858     IWineD3DDeviceImpl_GetVertexShaderConstantB,
5859     IWineD3DDeviceImpl_SetVertexShaderConstantI,
5860     IWineD3DDeviceImpl_GetVertexShaderConstantI,
5861     IWineD3DDeviceImpl_SetVertexShaderConstantF,
5862     IWineD3DDeviceImpl_GetVertexShaderConstantF,
5863     IWineD3DDeviceImpl_SetViewport,
5864     IWineD3DDeviceImpl_GetViewport,
5865     IWineD3DDeviceImpl_MultiplyTransform,
5866     IWineD3DDeviceImpl_ValidateDevice,
5867     IWineD3DDeviceImpl_ProcessVertices,
5868     /*** State block ***/
5869     IWineD3DDeviceImpl_BeginStateBlock,
5870     IWineD3DDeviceImpl_EndStateBlock,
5871     /*** Scene management ***/
5872     IWineD3DDeviceImpl_BeginScene,
5873     IWineD3DDeviceImpl_EndScene,
5874     IWineD3DDeviceImpl_Present,
5875     IWineD3DDeviceImpl_Clear,
5876     /*** Drawing ***/
5877     IWineD3DDeviceImpl_DrawPrimitive,
5878     IWineD3DDeviceImpl_DrawIndexedPrimitive,
5879     IWineD3DDeviceImpl_DrawPrimitiveUP,
5880     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5881     IWineD3DDeviceImpl_DrawRectPatch,
5882     IWineD3DDeviceImpl_DrawTriPatch,
5883     IWineD3DDeviceImpl_DeletePatch,
5884     IWineD3DDeviceImpl_ColorFill,
5885     IWineD3DDeviceImpl_UpdateTexture,
5886     IWineD3DDeviceImpl_UpdateSurface,
5887     IWineD3DDeviceImpl_StretchRect,
5888     IWineD3DDeviceImpl_GetRenderTargetData,
5889     IWineD3DDeviceImpl_GetFrontBufferData,
5890     /*** Internal use IWineD3DDevice methods ***/
5891     IWineD3DDeviceImpl_SetupTextureStates,
5892     /*** object tracking ***/
5893     IWineD3DDeviceImpl_SwapChainReleased,
5894     IWineD3DDeviceImpl_ResourceReleased
5895 };
5896
5897
5898 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5899     WINED3DRS_ALPHABLENDENABLE   ,
5900     WINED3DRS_ALPHAFUNC          ,
5901     WINED3DRS_ALPHAREF           ,
5902     WINED3DRS_ALPHATESTENABLE    ,
5903     WINED3DRS_BLENDOP            ,
5904     WINED3DRS_COLORWRITEENABLE   ,
5905     WINED3DRS_DESTBLEND          ,
5906     WINED3DRS_DITHERENABLE       ,
5907     WINED3DRS_FILLMODE           ,
5908     WINED3DRS_FOGDENSITY         ,
5909     WINED3DRS_FOGEND             ,
5910     WINED3DRS_FOGSTART           ,
5911     WINED3DRS_LASTPIXEL          ,
5912     WINED3DRS_SHADEMODE          ,
5913     WINED3DRS_SRCBLEND           ,
5914     WINED3DRS_STENCILENABLE      ,
5915     WINED3DRS_STENCILFAIL        ,
5916     WINED3DRS_STENCILFUNC        ,
5917     WINED3DRS_STENCILMASK        ,
5918     WINED3DRS_STENCILPASS        ,
5919     WINED3DRS_STENCILREF         ,
5920     WINED3DRS_STENCILWRITEMASK   ,
5921     WINED3DRS_STENCILZFAIL       ,
5922     WINED3DRS_TEXTUREFACTOR      ,
5923     WINED3DRS_WRAP0              ,
5924     WINED3DRS_WRAP1              ,
5925     WINED3DRS_WRAP2              ,
5926     WINED3DRS_WRAP3              ,
5927     WINED3DRS_WRAP4              ,
5928     WINED3DRS_WRAP5              ,
5929     WINED3DRS_WRAP6              ,
5930     WINED3DRS_WRAP7              ,
5931     WINED3DRS_ZENABLE            ,
5932     WINED3DRS_ZFUNC              ,
5933     WINED3DRS_ZWRITEENABLE
5934 };
5935
5936 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5937     WINED3DTSS_ADDRESSW              ,
5938     WINED3DTSS_ALPHAARG0             ,
5939     WINED3DTSS_ALPHAARG1             ,
5940     WINED3DTSS_ALPHAARG2             ,
5941     WINED3DTSS_ALPHAOP               ,
5942     WINED3DTSS_BUMPENVLOFFSET        ,
5943     WINED3DTSS_BUMPENVLSCALE         ,
5944     WINED3DTSS_BUMPENVMAT00          ,
5945     WINED3DTSS_BUMPENVMAT01          ,
5946     WINED3DTSS_BUMPENVMAT10          ,
5947     WINED3DTSS_BUMPENVMAT11          ,
5948     WINED3DTSS_COLORARG0             ,
5949     WINED3DTSS_COLORARG1             ,
5950     WINED3DTSS_COLORARG2             ,
5951     WINED3DTSS_COLOROP               ,
5952     WINED3DTSS_RESULTARG             ,
5953     WINED3DTSS_TEXCOORDINDEX         ,
5954     WINED3DTSS_TEXTURETRANSFORMFLAGS
5955 };
5956
5957 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5958     WINED3DSAMP_ADDRESSU         ,
5959     WINED3DSAMP_ADDRESSV         ,
5960     WINED3DSAMP_ADDRESSW         ,
5961     WINED3DSAMP_BORDERCOLOR      ,
5962     WINED3DSAMP_MAGFILTER        ,
5963     WINED3DSAMP_MINFILTER        ,
5964     WINED3DSAMP_MIPFILTER        ,
5965     WINED3DSAMP_MIPMAPLODBIAS    ,
5966     WINED3DSAMP_MAXMIPLEVEL      ,
5967     WINED3DSAMP_MAXANISOTROPY    ,
5968     WINED3DSAMP_SRGBTEXTURE      ,
5969     WINED3DSAMP_ELEMENTINDEX
5970 };
5971
5972 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5973     WINED3DRS_AMBIENT                       ,
5974     WINED3DRS_AMBIENTMATERIALSOURCE         ,
5975     WINED3DRS_CLIPPING                      ,
5976     WINED3DRS_CLIPPLANEENABLE               ,
5977     WINED3DRS_COLORVERTEX                   ,
5978     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
5979     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
5980     WINED3DRS_FOGDENSITY                    ,
5981     WINED3DRS_FOGEND                        ,
5982     WINED3DRS_FOGSTART                      ,
5983     WINED3DRS_FOGTABLEMODE                  ,
5984     WINED3DRS_FOGVERTEXMODE                 ,
5985     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
5986     WINED3DRS_LIGHTING                      ,
5987     WINED3DRS_LOCALVIEWER                   ,
5988     WINED3DRS_MULTISAMPLEANTIALIAS          ,
5989     WINED3DRS_MULTISAMPLEMASK               ,
5990     WINED3DRS_NORMALIZENORMALS              ,
5991     WINED3DRS_PATCHEDGESTYLE                ,
5992     WINED3DRS_POINTSCALE_A                  ,
5993     WINED3DRS_POINTSCALE_B                  ,
5994     WINED3DRS_POINTSCALE_C                  ,
5995     WINED3DRS_POINTSCALEENABLE              ,
5996     WINED3DRS_POINTSIZE                     ,
5997     WINED3DRS_POINTSIZE_MAX                 ,
5998     WINED3DRS_POINTSIZE_MIN                 ,
5999     WINED3DRS_POINTSPRITEENABLE             ,
6000     WINED3DRS_RANGEFOGENABLE                ,
6001     WINED3DRS_SPECULARMATERIALSOURCE        ,
6002     WINED3DRS_TWEENFACTOR                   ,
6003     WINED3DRS_VERTEXBLEND
6004 };
6005
6006 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6007     WINED3DTSS_TEXCOORDINDEX         ,
6008     WINED3DTSS_TEXTURETRANSFORMFLAGS
6009 };
6010
6011 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6012     WINED3DSAMP_DMAPOFFSET
6013 };