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