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