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