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