wined3d: Better warn/fixme for query handling.
[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
333     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
334     if (IsEqualGUID(riid, &IID_IUnknown)
335         || IsEqualGUID(riid, &IID_IWineD3DBase)
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     /* "Standalone" surface */
729     IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
730
731     object->currentDesc.Width      = Width;
732     object->currentDesc.Height     = Height;
733     object->currentDesc.MultiSampleType    = MultiSample;
734     object->currentDesc.MultiSampleQuality = MultisampleQuality;
735
736     /* Setup some glformat defaults */
737     if (WINED3DFMT_UNKNOWN != Format) {
738         object->glDescription.glFormat         = D3DFmt2GLFmt(This, object->resource.format);
739         object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
740         object->glDescription.glType           = D3DFmt2GLType(This, object->resource.format);
741     } else {
742         object->glDescription.glFormat         = 0;
743         object->glDescription.glFormatInternal = 0;
744         object->glDescription.glType           = 0;
745     }
746
747     object->glDescription.textureName      = 0;
748     object->glDescription.level            = Level;
749     object->glDescription.target           = GL_TEXTURE_2D;
750
751     /* Internal data */
752     object->pow2Width  = pow2Width;
753     object->pow2Height = pow2Height;
754     object->nonpow2    = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
755     object->discard    = Discard;
756     object->activeLock = FALSE;
757
758     if (WINED3DFMT_UNKNOWN != Format) {
759         object->bytesPerPixel = D3DFmtGetBpp(This, Format);
760         object->pow2Size      = (pow2Width * object->bytesPerPixel) * pow2Height;
761     } else {
762         object->bytesPerPixel = 0;
763         object->pow2Size      = 0;
764     }
765
766     /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
767
768     TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
769
770     /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
771     * this function is too deap to need to care about things like this.
772     * Levels need to be checked too, and possibly Type wince they all affect what can be done.
773     * ****************************************/
774     switch(Pool) {
775     case D3DPOOL_SCRATCH:
776         if(Lockable == FALSE)
777             FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
778                 which are mutually exclusive, setting lockable to true\n");
779                 Lockable = TRUE;
780     break;
781     case D3DPOOL_SYSTEMMEM:
782         if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
783                                     this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
784     case D3DPOOL_MANAGED:
785         if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
786                                              Usage of DYNAMIC which are mutually exclusive, not doing \
787                                              anything just telling you.\n");
788     break;
789     case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
790         if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
791            && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
792             FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
793     break;
794     default:
795         FIXME("(%p) Unknown pool %d\n", This, Pool);
796     break;
797     };
798
799     if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
800         FIXME("Trying to create a render target that isn't in the default pool\n");
801     }
802
803
804     object->locked   = FALSE;
805     object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
806
807     /* mark the texture as dirty so that it get's loaded first time around*/
808     IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
809     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
810            This, Width, Height, Format, debug_d3dformat(Format),
811            (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
812     return D3D_OK;
813
814 }
815
816 HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
817                                                  DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
818                                                  IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
819                                                  D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
820
821     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
822     IWineD3DTextureImpl *object;
823     unsigned int i;
824     UINT tmpW;
825     UINT tmpH;
826     HRESULT hr;
827     unsigned int pow2Width  = Width;
828     unsigned int pow2Height = Height;
829
830
831     TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This, Width, Height, Levels, Usage);
832
833     /* TODO: It should only be possible to create textures for formats 
834              that are reported as supported */
835     if (WINED3DFMT_UNKNOWN >= Format) {
836         WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
837         return D3DERR_INVALIDCALL;
838     }
839
840     D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
841     D3DINITIALIZEBASETEXTURE(object->baseTexture);    
842     object->width  = Width;
843     object->height = Height;
844
845     /** Non-power2 support **/
846     /* Find the nearest pow2 match */
847     pow2Width = pow2Height = 1;
848     while (pow2Width < Width) pow2Width <<= 1;
849     while (pow2Height < Height) pow2Height <<= 1;
850
851     /** FIXME: add support for real non-power-two if it's provided by the video card **/
852     /* Precalculated scaling for 'faked' non power of two texture coords */
853     object->pow2scalingFactorX  =  (((float)Width)  / ((float)pow2Width));
854     object->pow2scalingFactorY  =  (((float)Height) / ((float)pow2Height));
855     TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
856
857     /* Calculate levels for mip mapping */
858     if (Levels == 0) {
859         TRACE("calculating levels %d\n", object->baseTexture.levels);
860         object->baseTexture.levels++;
861         tmpW = Width;
862         tmpH = Height;
863         while (tmpW > 1 && tmpH > 1) {
864             tmpW = max(1, tmpW >> 1);
865             tmpH = max(1, tmpH >> 1);
866             object->baseTexture.levels++;
867         }
868         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
869     }
870
871     /* Generate all the surfaces */
872     tmpW = Width;
873     tmpH = Height;
874     for (i = 0; i < object->baseTexture.levels; i++)
875     {
876         /* use the callback to create the texture surface */
877         hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
878         if (hr!= D3D_OK) {
879             int j;
880             FIXME("Failed to create surface  %p\n", object);
881             /* clean up */
882             for (j = 0 ; j < i ; j++) {
883                 IWineD3DSurface_Release(object->surfaces[j]);
884             }
885             /* heap free object */
886             HeapFree(GetProcessHeap(), 0, object);
887
888             *ppTexture = NULL;
889             return hr;
890         }
891
892         IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
893         TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
894         /* calculate the next mipmap level */
895         tmpW = max(1, tmpW >> 1);
896         tmpH = max(1, tmpH >> 1);
897     }
898
899     TRACE("(%p) : Created  texture %p\n", This, object);
900     return D3D_OK;
901 }
902
903 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
904                                                       UINT Width, UINT Height, UINT Depth,
905                                                       UINT Levels, DWORD Usage,
906                                                       WINED3DFORMAT Format, D3DPOOL Pool,
907                                                       IWineD3DVolumeTexture **ppVolumeTexture,
908                                                       HANDLE *pSharedHandle, IUnknown *parent,
909                                                       D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
910
911     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
912     IWineD3DVolumeTextureImpl *object;
913     unsigned int               i;
914     UINT                       tmpW;
915     UINT                       tmpH;
916     UINT                       tmpD;
917
918     /* TODO: It should only be possible to create textures for formats 
919              that are reported as supported */
920     if (WINED3DFMT_UNKNOWN >= Format) {
921         WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
922         return D3DERR_INVALIDCALL;
923     }
924
925     D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
926     D3DINITIALIZEBASETEXTURE(object->baseTexture);
927
928     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
929           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
930
931     object->width  = Width;
932     object->height = Height;
933     object->depth  = Depth;
934
935     /* Calculate levels for mip mapping */
936     if (Levels == 0) {
937         object->baseTexture.levels++;
938         tmpW = Width;
939         tmpH = Height;
940         tmpD = Depth;
941         while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
942             tmpW = max(1, tmpW >> 1);
943             tmpH = max(1, tmpH >> 1);
944             tmpD = max(1, tmpD >> 1);
945             object->baseTexture.levels++;
946         }
947         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
948     }
949
950     /* Generate all the surfaces */
951     tmpW = Width;
952     tmpH = Height;
953     tmpD = Depth;
954
955     for (i = 0; i < object->baseTexture.levels; i++)
956     {
957         /* Create the volume */
958         D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
959                            (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
960
961         /* Set it's container to this object */
962         IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
963
964         /* calcualte the next mipmap level */
965         tmpW = max(1, tmpW >> 1);
966         tmpH = max(1, tmpH >> 1);
967         tmpD = max(1, tmpD >> 1);
968     }
969
970     *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
971     TRACE("(%p) : Created volume texture %p\n", This, object);
972     return D3D_OK;
973 }
974
975 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
976                                                UINT Width, UINT Height, UINT Depth,
977                                                DWORD Usage,
978                                                WINED3DFORMAT Format, D3DPOOL Pool,
979                                                IWineD3DVolume** ppVolume,
980                                                HANDLE* pSharedHandle, IUnknown *parent) {
981
982     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
983     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
984
985     D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
986
987     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
988           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
989
990     object->currentDesc.Width   = Width;
991     object->currentDesc.Height  = Height;
992     object->currentDesc.Depth   = Depth;
993     object->bytesPerPixel       = D3DFmtGetBpp(This, Format);
994
995     /** Note: Volume textures cannot be dxtn, hence no need to check here **/
996     object->lockable            = TRUE;
997     object->locked              = FALSE;
998     memset(&object->lockedBox, 0, sizeof(D3DBOX));
999     object->dirty               = TRUE;
1000
1001     return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1002 }
1003
1004 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1005                                                     UINT Levels, DWORD Usage,
1006                                                     WINED3DFORMAT Format, D3DPOOL Pool,
1007                                                     IWineD3DCubeTexture **ppCubeTexture,
1008                                                     HANDLE *pSharedHandle, IUnknown *parent,
1009                                                     D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1010
1011     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1012     IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1013     unsigned int             i, j;
1014     UINT                     tmpW;
1015     HRESULT                  hr;
1016     unsigned int pow2EdgeLength  = EdgeLength;
1017
1018     /* TODO: It should only be possible to create textures for formats 
1019              that are reported as supported */
1020     if (WINED3DFMT_UNKNOWN >= Format) {
1021         WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This);
1022         return D3DERR_INVALIDCALL;
1023     }
1024
1025     D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
1026     D3DINITIALIZEBASETEXTURE(object->baseTexture);
1027
1028     TRACE("(%p) Create Cube Texture\n", This);
1029
1030     /** Non-power2 support **/
1031
1032     /* Find the nearest pow2 match */
1033     pow2EdgeLength = 1;
1034     while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1035
1036     object->edgeLength           = EdgeLength;
1037     /* TODO: support for native non-power 2 */
1038     /* Precalculated scaling for 'faked' non power of two texture coords */
1039     object->pow2scalingFactor    = ((float)EdgeLength) / ((float)pow2EdgeLength);
1040
1041     /* Calculate levels for mip mapping */
1042     if (Levels == 0) {
1043         object->baseTexture.levels++;
1044         tmpW = EdgeLength;
1045         while (tmpW > 1) {
1046             tmpW = max(1, tmpW >> 1);
1047             object->baseTexture.levels++;
1048         }
1049         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1050     }
1051
1052     /* Generate all the surfaces */
1053     tmpW = EdgeLength;
1054     for (i = 0; i < object->baseTexture.levels; i++) {
1055
1056         /* Create the 6 faces */
1057         for (j = 0; j < 6; j++) {
1058
1059             hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
1060                                    i /* Level */, &object->surfaces[j][i],pSharedHandle);
1061
1062             if(hr!= D3D_OK) {
1063                 /* clean up */
1064                 int k;
1065                 int l;
1066                 for (l = 0; l < j; l++) {
1067                     IWineD3DSurface_Release(object->surfaces[j][i]);
1068                 }
1069                 for (k = 0; k < i; k++) {
1070                     for (l = 0; l < 6; l++) {
1071                     IWineD3DSurface_Release(object->surfaces[l][j]);
1072                     }
1073                 }
1074
1075                 FIXME("(%p) Failed to create surface\n",object);
1076                 HeapFree(GetProcessHeap(),0,object);
1077                 *ppCubeTexture = NULL;
1078                 return hr;
1079             }
1080             IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1081             TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1082         }
1083         tmpW = max(1, tmpW >> 1);
1084     }
1085
1086     TRACE("(%p) : Created Cube Texture %p\n", This, object);
1087     *ppCubeTexture = (IWineD3DCubeTexture *) object;
1088     return D3D_OK;
1089 }
1090
1091 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1092     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1093     IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1094
1095     if (NULL == ppQuery) {
1096         /* Just a check to see if we support this type of query */
1097         HRESULT hr = D3DERR_NOTAVAILABLE;
1098         switch(Type) {
1099         case WINED3DQUERYTYPE_OCCLUSION:
1100             TRACE("(%p) occlusion query\n", This);
1101             if (GL_SUPPORT(ARB_OCCLUSION_QUERY) || GL_SUPPORT(NV_OCCLUSION_QUERY))
1102                 hr = D3D_OK;
1103             else
1104                 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1105             break;
1106         case WINED3DQUERYTYPE_VCACHE:
1107         case WINED3DQUERYTYPE_RESOURCEMANAGER:
1108         case WINED3DQUERYTYPE_VERTEXSTATS:
1109         case WINED3DQUERYTYPE_EVENT:
1110         case WINED3DQUERYTYPE_TIMESTAMP:
1111         case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1112         case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1113         case WINED3DQUERYTYPE_PIPELINETIMINGS:
1114         case WINED3DQUERYTYPE_INTERFACETIMINGS:
1115         case WINED3DQUERYTYPE_VERTEXTIMINGS:
1116         case WINED3DQUERYTYPE_PIXELTIMINGS:
1117         case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1118         case WINED3DQUERYTYPE_CACHEUTILIZATION:
1119         default:
1120             FIXME("(%p) Unhandled query type %d\n", This, Type);
1121         }
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, (IWineD3DBase *)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, (IWineD3DBase *)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, (IWineD3DBase *)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         /*
3500          * POINTSCALEENABLE controls how point size value is treated. If set to
3501          * true, the point size is scaled with repsect to height of viewport.
3502          * When set to false point size is in pixels.
3503          *
3504          * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3505          */
3506
3507         /* Default values */
3508         GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3509         
3510         /*
3511          * Minium valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3512          * This means that OpenGL will clamp really small point sizes to 1.0f.
3513          * To correct for this we need to multiply by the scale factor when sizes
3514          * are less than 1.0f. scale_factor =  1.0f / point_size.
3515          */
3516         GLfloat pointSize = *((float*)&This->stateBlock->renderState[D3DRS_POINTSIZE]);
3517         GLfloat scaleFactor;
3518         if(pointSize < 1.0f) {
3519             scaleFactor = pointSize * pointSize;
3520         } else {
3521             scaleFactor = 1.0f;
3522         }
3523         
3524         if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3525             att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3526                 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3527             att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3528                 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3529             att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3530                 (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3531         }
3532
3533         if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3534             GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3535             checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3536         }
3537         else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3538             GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3539             checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3540         } else {
3541             TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3542         }
3543         break;
3544     }
3545     case WINED3DRS_COLORWRITEENABLE          :
3546       {
3547         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3548               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
3549               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3550               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
3551               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3552         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE,
3553                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3554                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
3555                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3556         checkGLcall("glColorMask(...)");
3557       }
3558       break;
3559
3560     case WINED3DRS_LOCALVIEWER               :
3561       {
3562         GLint state = (Value) ? 1 : 0;
3563         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3564         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3565       }
3566       break;
3567
3568     case WINED3DRS_LASTPIXEL                 :
3569       {
3570         if (Value) {
3571           TRACE("Last Pixel Drawing Enabled\n");
3572         } else {
3573           FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3574         }
3575       }
3576       break;
3577
3578     case WINED3DRS_SOFTWAREVERTEXPROCESSING  :
3579       {
3580         if (Value) {
3581           TRACE("Software Processing Enabled\n");
3582         } else {
3583           TRACE("Software Processing Disabled\n");
3584         }
3585       }
3586       break;
3587
3588       /** not supported */
3589     case WINED3DRS_ZVISIBLE                  :
3590       {
3591         LEAVE_GL();
3592         return D3DERR_INVALIDCALL;
3593       }
3594     case WINED3DRS_POINTSPRITEENABLE         :
3595     {
3596         /* TODO: NV_POINT_SPRITE */
3597         if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3598             TRACE("Point sprites not supported\n");
3599             break;
3600         }
3601
3602         /*
3603          * Point sprites are always enabled. Value controls texture coordinate
3604          * replacement mode. Must be set true for point sprites to use
3605          * textures.
3606          */
3607         glEnable(GL_POINT_SPRITE_ARB);
3608         checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3609
3610         if (Value) {
3611             glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3612             checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3613         } else {
3614             glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3615             checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3616         }
3617         break;
3618     }
3619     case WINED3DRS_EDGEANTIALIAS             :
3620     {
3621         if(Value) {
3622             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3623             glEnable(GL_BLEND);
3624             checkGLcall("glEnable(GL_BLEND)");
3625             glEnable(GL_LINE_SMOOTH);
3626             checkGLcall("glEnable(GL_LINE_SMOOTH)");
3627         } else {
3628             glDisable(GL_BLEND);
3629             checkGLcall("glDisable(GL_BLEND)");
3630             glDisable(GL_LINE_SMOOTH);
3631             checkGLcall("glDisable(GL_LINE_SMOOTH)");
3632         }
3633         break;
3634     }
3635     case WINED3DRS_WRAP0                     :
3636     case WINED3DRS_WRAP1                     :
3637     case WINED3DRS_WRAP2                     :
3638     case WINED3DRS_WRAP3                     :
3639     case WINED3DRS_WRAP4                     :
3640     case WINED3DRS_WRAP5                     :
3641     case WINED3DRS_WRAP6                     :
3642     case WINED3DRS_WRAP7                     :
3643     /**
3644     http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3645     http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3646     http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3647     Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3648     http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3649
3650     so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3651     */
3652     TRACE("(%p)->(%d,%ld) Texture wraping not yet supported\n",This, State, Value);
3653     break;
3654     case WINED3DRS_MULTISAMPLEANTIALIAS      :
3655     {
3656         if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3657             TRACE("Multisample antialiasing not supported\n");
3658             break;
3659         }
3660
3661         if(Value) {
3662             glEnable(GL_MULTISAMPLE_ARB);
3663             checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3664         } else {
3665             glDisable(GL_MULTISAMPLE_ARB);
3666             checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3667         }
3668         break;
3669     }
3670     case WINED3DRS_MULTISAMPLEMASK           :
3671     case WINED3DRS_PATCHEDGESTYLE            :
3672     case WINED3DRS_PATCHSEGMENTS             :
3673     case WINED3DRS_DEBUGMONITORTOKEN         :
3674     case WINED3DRS_POSITIONORDER             :
3675     case WINED3DRS_NORMALORDER               :
3676         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3677         FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3678         break;
3679     default:
3680         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3681     }
3682
3683     LEAVE_GL();
3684
3685     return D3D_OK;
3686 }
3687
3688 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3689     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3690     TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3691     *pValue = This->stateBlock->renderState[State];
3692     return D3D_OK;
3693 }
3694
3695 /*****
3696  * Get / Set Sampler States
3697  * TODO: Verify against dx9 definitions
3698  *****/
3699
3700 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3701     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3702     /**
3703     * SetSampler is designed to allow for more than the standard up to 8 textures
3704     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
3705     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3706     *
3707     * http://developer.nvidia.com/object/General_FAQ.html#t6
3708     *
3709     * There are two new settings for GForce
3710     * the sampler one:
3711     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3712     * and the texture one:
3713     * GL_MAX_TEXTURE_COORDS_ARB.
3714     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3715      ******************/
3716     /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3717     TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3718
3719     if(Sampler >  GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3720          FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3721         return D3DERR_INVALIDCALL;
3722     }
3723     TRACE("Setting sampler %ld %d to %ld\n", Sampler, Type, Value);
3724     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
3725     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
3726     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3727
3728     /* Handle recording of state blocks */
3729     if (This->isRecordingState) {
3730         TRACE("Recording... not performing anything\n");
3731         return D3D_OK;
3732     }
3733
3734     return D3D_OK;
3735 }
3736
3737 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3738     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3739     /** TODO: check that sampler is in  range **/
3740     *Value = This->updateStateBlock->samplerState[Sampler][Type];
3741     TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3742
3743     return D3D_OK;
3744 }
3745
3746 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3747     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3748     ENTER_GL();
3749
3750     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3751     TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3752     glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3753     LEAVE_GL();
3754
3755     return D3D_OK;
3756 }
3757
3758 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3759     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3760     GLint scissorBox[4];
3761
3762     ENTER_GL();
3763     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3764     glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3765     pRect->left = scissorBox[1];
3766     pRect->top = scissorBox[2];
3767     pRect->right = scissorBox[1] + scissorBox[3];
3768     pRect->bottom = scissorBox[2] + scissorBox[4];
3769     TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3770     LEAVE_GL();
3771     return D3D_OK;
3772 }
3773
3774 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3775     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3776     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3777
3778     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3779
3780     This->updateStateBlock->vertexDecl = pDecl;
3781     This->updateStateBlock->changed.vertexDecl = TRUE;
3782     This->updateStateBlock->set.vertexDecl = TRUE;
3783
3784     if (This->isRecordingState) {
3785         TRACE("Recording... not performing anything\n");
3786     }
3787
3788     if (NULL != pDecl) {
3789         IWineD3DVertexDeclaration_AddRef(pDecl);
3790     }
3791     if (NULL != oldDecl) {
3792         IWineD3DVertexDeclaration_Release(oldDecl);
3793     }
3794     return D3D_OK;
3795 }
3796
3797 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3798     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3799
3800     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3801
3802     *ppDecl = This->stateBlock->vertexDecl;
3803     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3804     return D3D_OK;
3805 }
3806
3807 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3808     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3809     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3810
3811     This->updateStateBlock->vertexShader         = pShader;
3812     This->updateStateBlock->changed.vertexShader = TRUE;
3813     This->updateStateBlock->set.vertexShader     = TRUE;
3814
3815     if (This->isRecordingState) {
3816         TRACE("Recording... not performing anything\n");
3817     }
3818
3819     if (NULL != pShader) {
3820         IWineD3DVertexShader_AddRef(pShader);
3821     }
3822     if (NULL != oldShader) {
3823         IWineD3DVertexShader_Release(oldShader);
3824     }
3825
3826     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3827     /**
3828      * TODO: merge HAL shaders context switching from prototype
3829      */
3830     return D3D_OK;
3831 }
3832
3833 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3834     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3835
3836     if (NULL == ppShader) {
3837         return D3DERR_INVALIDCALL;
3838     }
3839     *ppShader = This->stateBlock->vertexShader;
3840     if( NULL != *ppShader)
3841         IWineD3DVertexShader_AddRef(*ppShader);
3842
3843     TRACE("(%p) : returning %p\n", This, *ppShader);
3844     return D3D_OK;
3845 }
3846
3847 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
3848     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3849
3850     int i;
3851     int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
3852
3853     TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
3854             iface, dstData, srcData, type, start, count, registersize);
3855
3856     if (type != WINESHADERCNST_NONE) {
3857         if (srcData == NULL || cnt < 0) {
3858             return D3DERR_INVALIDCALL;
3859         }
3860
3861         CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
3862     }
3863
3864     for (i = start; i < cnt + start; ++i) {
3865         This->updateStateBlock->changed.vertexShaderConstants[i] = TRUE;
3866         This->updateStateBlock->set.vertexShaderConstants[i]     = TRUE;
3867         This->updateStateBlock->vertexShaderConstantT[i]         = type;
3868     }
3869
3870     return D3D_OK;
3871 }
3872
3873 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
3874     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3875
3876     int i;
3877     int cnt = min(count, MAX_VSHADER_CONSTANTS - (start + 1));
3878
3879     TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
3880             iface, dstData, srcData, type, start, count, registersize);
3881
3882     /* Verify that the requested shader constant was populated with the correct type */
3883     for (i = start; i < cnt + start; ++i) {
3884         if (This->updateStateBlock->vertexShaderConstantT[i] != type) {
3885             TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n", 
3886                     This, type, This->updateStateBlock->vertexShaderConstantT[i]);
3887             return D3DERR_INVALIDCALL;
3888         }
3889     }
3890
3891     if (dstData == NULL || cnt < 0) {
3892         return D3DERR_INVALIDCALL;
3893     }
3894
3895     CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
3896
3897     return D3D_OK;
3898 }
3899
3900 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL  *pConstantData, UINT BoolCount){
3901     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3902     
3903     return IWineD3DDeviceImpl_SetVertexShaderConstant(iface, 
3904             This->updateStateBlock->vertexShaderConstantB, 
3905             pConstantData, 
3906             WINESHADERCNST_BOOL, 
3907             StartRegister, 
3908             BoolCount, 
3909             sizeof(*pConstantData));
3910 }
3911
3912 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3913     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3914     
3915     return IWineD3DDeviceImpl_GetVertexShaderConstant(iface, 
3916             pConstantData, 
3917             This->updateStateBlock->vertexShaderConstantB, 
3918             WINESHADERCNST_BOOL, 
3919             StartRegister, 
3920             BoolCount, 
3921             sizeof(*pConstantData));
3922 }
3923
3924 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3925     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3926     
3927     return IWineD3DDeviceImpl_SetVertexShaderConstant(iface, 
3928             This->updateStateBlock->vertexShaderConstantI, 
3929             pConstantData, 
3930             WINESHADERCNST_INTEGER, 
3931             StartRegister, 
3932             Vector4iCount, 
3933             4 * sizeof(*pConstantData));
3934 }
3935
3936 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int         *pConstantData, UINT Vector4iCount){
3937     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3938     
3939     return IWineD3DDeviceImpl_GetVertexShaderConstant(iface, 
3940             pConstantData, 
3941             This->updateStateBlock->vertexShaderConstantI, 
3942             WINESHADERCNST_INTEGER, 
3943             StartRegister, 
3944             Vector4iCount, 
3945             4 * sizeof(*pConstantData));
3946 }
3947
3948
3949 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3950     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3951
3952     return IWineD3DDeviceImpl_SetVertexShaderConstant(iface, 
3953             This->updateStateBlock->vertexShaderConstantF, 
3954             pConstantData, 
3955             WINESHADERCNST_FLOAT, 
3956             StartRegister, 
3957             Vector4fCount, 
3958             4 * sizeof(*pConstantData));
3959 }
3960
3961 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float       *pConstantData, UINT Vector4fCount){
3962     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3963
3964     return IWineD3DDeviceImpl_GetVertexShaderConstant(iface, 
3965             pConstantData, 
3966             This->updateStateBlock->vertexShaderConstantF, 
3967             WINESHADERCNST_FLOAT, 
3968             StartRegister, 
3969             Vector4fCount, 
3970             4 * sizeof(*pConstantData));
3971 }
3972
3973 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
3974     return IWineD3DDeviceImpl_SetVertexShaderConstant(iface, 
3975             NULL, 
3976             NULL, 
3977             WINESHADERCNST_NONE, 
3978             StartRegister, 
3979             VectorNCount, 
3980             0);
3981 }
3982
3983 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3984     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3985     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3986     This->updateStateBlock->pixelShader         = pShader;
3987     This->updateStateBlock->changed.pixelShader = TRUE;
3988     This->updateStateBlock->set.pixelShader     = TRUE;
3989
3990     /* Handle recording of state blocks */
3991     if (This->isRecordingState) {
3992         TRACE("Recording... not performing anything\n");
3993     }
3994
3995     if (NULL != pShader) {
3996         IWineD3DPixelShader_AddRef(pShader);
3997     }
3998     if (NULL != oldShader) {
3999         IWineD3DPixelShader_Release(oldShader);
4000     }
4001
4002     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4003     /**
4004      * TODO: merge HAL shaders context switching from prototype
4005      */
4006     return D3D_OK;
4007 }
4008
4009 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4010     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4011
4012     if (NULL == ppShader) {
4013         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4014         return D3DERR_INVALIDCALL;
4015     }
4016
4017     *ppShader =  This->stateBlock->pixelShader;
4018     if (NULL != ppShader) {
4019         IWineD3DPixelShader_AddRef(*ppShader);
4020     }
4021     TRACE("(%p) : returning %p\n", This, *ppShader);
4022     return D3D_OK;
4023 }
4024
4025 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4026     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4027
4028     int i;
4029     int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4030
4031     TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4032             iface, dstData, srcData, type, start, count, registersize);
4033
4034     if (type != WINESHADERCNST_NONE) {
4035         if (srcData == NULL || cnt < 0) {
4036             return D3DERR_INVALIDCALL;
4037         }
4038
4039         CopyMemory((char *)dstData + (start * registersize), srcData, cnt * registersize);
4040     }
4041
4042     for (i = start; i < cnt + start; ++i) {
4043         This->updateStateBlock->changed.pixelShaderConstants[i] = TRUE;
4044         This->updateStateBlock->set.pixelShaderConstants[i]     = TRUE;
4045         This->updateStateBlock->pixelShaderConstantT[i]         = type;
4046     }
4047
4048     return D3D_OK;
4049 }
4050
4051 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice *iface, void *dstData, const void *srcData, UINT type, UINT start, UINT count, UINT registersize) {
4052     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4053
4054     int i;
4055     int cnt = min(count, MAX_PSHADER_CONSTANTS - (start + 1));
4056
4057     TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4058             iface, dstData, srcData, type, start, count, registersize);
4059
4060     /* Verify that the requested shader constant was populated with the correct type */
4061     for (i = start; i < cnt + start; ++i) {
4062         if (This->updateStateBlock->pixelShaderConstantT[i] != type) {
4063             TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning D3DERR_INVALIDCALL\n", 
4064                     This, type, This->updateStateBlock->pixelShaderConstantT[i]);
4065             return D3DERR_INVALIDCALL;
4066         }
4067     }
4068
4069     if (dstData == NULL || cnt < 0) {
4070         return D3DERR_INVALIDCALL;
4071     }
4072
4073     CopyMemory(dstData, (char *)srcData + (start * registersize), cnt * registersize);
4074
4075     return D3D_OK;
4076 }
4077
4078 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL   *pConstantData, UINT BoolCount) {
4079     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4080     
4081     return IWineD3DDeviceImpl_SetPixelShaderConstant(iface, 
4082             This->updateStateBlock->pixelShaderConstantB, 
4083             pConstantData, 
4084             WINESHADERCNST_BOOL, 
4085             StartRegister, 
4086             BoolCount, 
4087             sizeof(*pConstantData));
4088 }
4089
4090 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL         *pConstantData, UINT BoolCount) {
4091     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4092
4093     return IWineD3DDeviceImpl_GetPixelShaderConstant(iface, 
4094             pConstantData, 
4095             This->updateStateBlock->pixelShaderConstantB, 
4096             WINESHADERCNST_BOOL, 
4097             StartRegister, 
4098             BoolCount, 
4099             sizeof(*pConstantData));
4100 }
4101
4102 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int    *pConstantData, UINT Vector4iCount) {
4103     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4104
4105     return IWineD3DDeviceImpl_SetPixelShaderConstant(iface, 
4106             This->updateStateBlock->pixelShaderConstantI, 
4107             pConstantData, 
4108             WINESHADERCNST_INTEGER, 
4109             StartRegister, 
4110             Vector4iCount, 
4111             4 * sizeof(*pConstantData));
4112 }
4113
4114 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int          *pConstantData, UINT Vector4iCount) {
4115     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4116     
4117     return IWineD3DDeviceImpl_GetPixelShaderConstant(iface, 
4118             pConstantData, 
4119             This->updateStateBlock->pixelShaderConstantI, 
4120             WINESHADERCNST_INTEGER, 
4121             StartRegister, 
4122             Vector4iCount, 
4123             4 * sizeof(*pConstantData));
4124 }
4125
4126 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float  *pConstantData, UINT Vector4fCount) {
4127     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4128     
4129     return IWineD3DDeviceImpl_SetPixelShaderConstant(iface, 
4130             This->updateStateBlock->pixelShaderConstantF, 
4131             pConstantData, 
4132             WINESHADERCNST_FLOAT, 
4133             StartRegister, 
4134             Vector4fCount, 
4135             4 * sizeof(*pConstantData));
4136 }
4137
4138 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float        *pConstantData, UINT Vector4fCount) {
4139     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4140
4141     return IWineD3DDeviceImpl_GetPixelShaderConstant(iface, 
4142             pConstantData, 
4143             This->updateStateBlock->pixelShaderConstantF, 
4144             WINESHADERCNST_FLOAT, 
4145             StartRegister, 
4146             Vector4fCount, 
4147             4 * sizeof(*pConstantData));
4148 }
4149
4150 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice *iface, UINT StartRegister, UINT VectorNCount){
4151     return IWineD3DDeviceImpl_SetPixelShaderConstant(iface, 
4152             NULL, 
4153             NULL, 
4154             WINESHADERCNST_NONE, 
4155             StartRegister, 
4156             VectorNCount, 
4157             0);
4158 }
4159
4160 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4161     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4162     FIXME("(%p) : stub\n", This);
4163     return D3D_OK;
4164 }
4165
4166 /*****
4167  * Apply / Get / Set Texture Stage States
4168  * TODO: Verify against dx9 definitions
4169  *****/
4170
4171 /* 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 */
4172 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4173     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4174     DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4175     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4176
4177     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4178
4179     /* Check that the stage is within limits  */
4180     if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4181         TRACE("Attempt to access invalid texture rejected\n");
4182         return;
4183     }
4184
4185     ENTER_GL();
4186
4187     switch (Type) {
4188     case WINED3DTSS_ALPHAOP               :
4189     case WINED3DTSS_COLOROP               :
4190         /* nothing to do as moved to drawprim for now */
4191         break;
4192     case WINED3DTSS_ADDRESSW              :
4193 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4194             if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4195                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
4196
4197             } else {
4198                 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4199                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4200                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4201                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4202             }
4203 #endif
4204     case WINED3DTSS_TEXCOORDINDEX         :
4205         {
4206             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4207
4208             /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4209                   one flag, you can still specify an index value, which the system uses to
4210                   determine the texture wrapping mode.
4211                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4212                   means use the vertex position (camera-space) as the input texture coordinates
4213                   for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4214                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4215                   to the TEXCOORDINDEX value */
4216
4217             /**
4218              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4219              */
4220             switch (Value & 0xFFFF0000) {
4221             case D3DTSS_TCI_PASSTHRU:
4222                 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4223                 glDisable(GL_TEXTURE_GEN_S);
4224                 glDisable(GL_TEXTURE_GEN_T);
4225                 glDisable(GL_TEXTURE_GEN_R);
4226                 glDisable(GL_TEXTURE_GEN_Q);
4227                 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4228                 break;
4229
4230             case D3DTSS_TCI_CAMERASPACEPOSITION:
4231                 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4232                     as the input texture coordinates for this stage's texture transformation. This
4233                     equates roughly to EYE_LINEAR                                                  */
4234                 {
4235                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4236                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4237                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4238                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4239                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4240     
4241                     glMatrixMode(GL_MODELVIEW);
4242                     glPushMatrix();
4243                     glLoadIdentity();
4244                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4245                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4246                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4247                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4248                     glPopMatrix();
4249     
4250                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4251                     glEnable(GL_TEXTURE_GEN_S);
4252                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4253                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4254                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4255                     glEnable(GL_TEXTURE_GEN_T);
4256                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4257                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4258                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4259                     glEnable(GL_TEXTURE_GEN_R);
4260                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4261                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4262                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4263                 }
4264                 break;
4265
4266             case D3DTSS_TCI_CAMERASPACENORMAL:
4267                 {
4268                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4269                         float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4270                         float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4271                         float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4272                         float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4273                         TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4274         
4275                         glMatrixMode(GL_MODELVIEW);
4276                         glPushMatrix();
4277                         glLoadIdentity();
4278                         glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4279                         glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4280                         glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4281                         glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4282                         glPopMatrix();
4283         
4284                         glEnable(GL_TEXTURE_GEN_S);
4285                         checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4286                         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4287                         checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4288                         glEnable(GL_TEXTURE_GEN_T);
4289                         checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4290                         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4291                         checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4292                         glEnable(GL_TEXTURE_GEN_R);
4293                         checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4294                         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4295                         checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4296                     }
4297                 }
4298                 break;
4299
4300             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4301                 {
4302                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4303                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4304                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4305                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4306                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4307                     TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4308     
4309                     glMatrixMode(GL_MODELVIEW);
4310                     glPushMatrix();
4311                     glLoadIdentity();
4312                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4313                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4314                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4315                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4316                     glPopMatrix();
4317     
4318                     glEnable(GL_TEXTURE_GEN_S);
4319                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4320                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4321                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4322                     glEnable(GL_TEXTURE_GEN_T);
4323                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4324                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4325                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4326                     glEnable(GL_TEXTURE_GEN_R);
4327                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4328                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4329                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4330                     }
4331                 }
4332                 break;
4333
4334             /* Unhandled types: */
4335             default:
4336                 /* Todo: */
4337                 /* ? disable GL_TEXTURE_GEN_n ? */
4338                 glDisable(GL_TEXTURE_GEN_S);
4339                 glDisable(GL_TEXTURE_GEN_T);
4340                 glDisable(GL_TEXTURE_GEN_R);
4341                 glDisable(GL_TEXTURE_GEN_Q);
4342                 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4343                 break;
4344             }
4345         }
4346         break;
4347
4348         /* Unhandled */
4349     case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4350         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);
4351         break;
4352
4353     case WINED3DTSS_BUMPENVMAT00          :
4354     case WINED3DTSS_BUMPENVMAT01          :
4355         TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4356         break;
4357     case WINED3DTSS_BUMPENVMAT10          :
4358     case WINED3DTSS_BUMPENVMAT11          :
4359         TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4360         break;
4361
4362     case WINED3DTSS_BUMPENVLSCALE         :
4363       TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4364       break;
4365
4366     case WINED3DTSS_BUMPENVLOFFSET        :
4367       TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4368       break;
4369
4370     case WINED3DTSS_RESULTARG             :
4371       TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4372       break;
4373
4374     default:
4375         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4376         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4377     }
4378
4379     LEAVE_GL();
4380
4381     return;
4382 }
4383
4384 /*****
4385  * Get / Set Texture Stage States
4386  * TODO: Verify against dx9 definitions
4387  *****/
4388 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4389     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4390
4391     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4392
4393     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4394
4395     /* Reject invalid texture units */
4396     if (Stage >= GL_LIMITS(textures)) {
4397         TRACE("Attempt to access invalid texture rejected\n");
4398         return D3DERR_INVALIDCALL;
4399     }
4400
4401     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4402     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
4403     This->updateStateBlock->textureState[Stage][Type]         = Value;
4404
4405     return D3D_OK;
4406 }
4407
4408 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4409     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4410     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4411     *pValue = This->updateStateBlock->textureState[Stage][Type];
4412     return D3D_OK;
4413 }
4414
4415 /*****
4416  * Get / Set Texture
4417  *****/
4418 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4419
4420     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4421     IWineD3DBaseTexture   *oldTexture;
4422
4423     oldTexture = This->updateStateBlock->textures[Stage];
4424     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4425
4426 #if 0 /* TODO: check so vertex textures */
4427     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4428         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4429         return D3D_OK;
4430     }
4431 #endif
4432
4433     /* Reject invalid texture units */
4434     if (Stage >= GL_LIMITS(textures) || Stage < 0) {
4435         WARN("Attempt to access invalid texture rejected\n");
4436         return D3DERR_INVALIDCALL;
4437     }
4438
4439     if(pTexture != NULL) {
4440         /* SetTexture isn't allowed on textures in D3DPOOL_SCRATCH; The same is
4441         *  the case for D3DPOOL_SYSTEMMEM textures unless D3DDEVCAPS_TEXTURESYSTEMMORY is set.
4442         *  We don't check the caps as GetDeviceCaps is inefficient and we don't set the cap anyway.
4443         */
4444         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == D3DPOOL_SCRATCH || ((IWineD3DTextureImpl*)pTexture)->resource.pool == D3DPOOL_SYSTEMMEM) {
4445             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4446             return D3DERR_INVALIDCALL;
4447         }
4448     }
4449
4450     oldTexture = This->updateStateBlock->textures[Stage];
4451     TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
4452     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4453
4454     This->updateStateBlock->set.textures[Stage]     = TRUE;
4455     This->updateStateBlock->changed.textures[Stage] = TRUE;
4456     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4457     This->updateStateBlock->textures[Stage]         = pTexture;
4458
4459     /* Handle recording of state blocks */
4460     if (This->isRecordingState) {
4461         TRACE("Recording... not performing anything\n");
4462         return D3D_OK;
4463     }
4464
4465     /** NOTE: MSDN says that setTexture increases the reference count,
4466     * and the the application nust set the texture back to null (or have a leaky application),
4467     * This means we should pass the refcount up to the parent
4468      *******************************/
4469     if (NULL != This->updateStateBlock->textures[Stage]) {
4470         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4471     }
4472
4473     if (NULL != oldTexture) {
4474         IWineD3DBaseTexture_Release(oldTexture);
4475     }
4476
4477     return D3D_OK;
4478 }
4479
4480 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4481     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4482     TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4483
4484     /* Reject invalid texture units */
4485     if (Stage >= GL_LIMITS(textures)) {
4486         TRACE("Attempt to access invalid texture rejected\n");
4487         return D3DERR_INVALIDCALL;
4488     }
4489     *ppTexture=This->updateStateBlock->textures[Stage];
4490     if (*ppTexture)
4491         IWineD3DBaseTexture_AddRef(*ppTexture);
4492     else
4493         return D3DERR_INVALIDCALL;
4494     return D3D_OK;
4495 }
4496
4497 /*****
4498  * Get Back Buffer
4499  *****/
4500 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4501                                                 IWineD3DSurface **ppBackBuffer) {
4502     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4503     IWineD3DSwapChain *swapChain;
4504     HRESULT hr;
4505
4506     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4507
4508     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4509     if (hr == D3D_OK) {
4510         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4511             IWineD3DSwapChain_Release(swapChain);
4512     } else {
4513         *ppBackBuffer = NULL;
4514     }
4515     return hr;
4516 }
4517
4518 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4519     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4520     WARN("(%p) : stub, calling idirect3d for now\n", This);
4521     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4522 }
4523
4524 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4525     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4526     IWineD3DSwapChain *swapChain;
4527     HRESULT hr;
4528
4529     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4530     if (hr == D3D_OK) {
4531         hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4532         IWineD3DSwapChain_Release(swapChain);
4533     } else {
4534         FIXME("(%p) Error getting display mode\n", This);
4535     }
4536     return hr;
4537 }
4538 /*****
4539  * Stateblock related functions
4540  *****/
4541
4542 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4543     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4544     IWineD3DStateBlockImpl *object;
4545     TRACE("(%p)", This);
4546     
4547     if (This->isRecordingState) {
4548         return D3DERR_INVALIDCALL;
4549     }
4550     
4551     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4552     if (NULL == object ) {
4553         FIXME("(%p)Error allocating memory for stateblock\n", This);
4554         return E_OUTOFMEMORY;
4555     }
4556     TRACE("(%p) creted object %p\n", This, object);
4557     object->wineD3DDevice= This;
4558     /** FIXME: object->parent       = parent; **/
4559     object->parent       = NULL;
4560     object->blockType    = WINED3DSBT_ALL;
4561     object->ref          = 1;
4562     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4563
4564     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4565     This->updateStateBlock = object;
4566     This->isRecordingState = TRUE;
4567
4568     TRACE("(%p) recording stateblock %p\n",This , object);
4569     return D3D_OK;
4570 }
4571
4572 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4573     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4574
4575     if (!This->isRecordingState) {
4576         FIXME("(%p) not recording! returning error\n", This);
4577         *ppStateBlock = NULL;
4578         return D3DERR_INVALIDCALL;
4579     }
4580
4581     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4582     This->isRecordingState = FALSE;
4583     This->updateStateBlock = This->stateBlock;
4584     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4585     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4586     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4587     return D3D_OK;
4588 }
4589
4590 /*****
4591  * Scene related functions
4592  *****/
4593 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4594     /* At the moment we have no need for any functionality at the beginning
4595        of a scene                                                          */
4596     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4597     TRACE("(%p) : stub\n", This);
4598     return D3D_OK;
4599 }
4600
4601 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4602     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4603     TRACE("(%p)\n", This);
4604     ENTER_GL();
4605     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4606     glFlush();
4607     checkGLcall("glFlush");
4608
4609     TRACE("End Scene\n");
4610     if(This->renderTarget != NULL) {
4611
4612         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4613         IUnknown *targetContainer = NULL;
4614         if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4615             || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4616             TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4617             /** always dirtify for now. we must find a better way to see that surface have been modified
4618             (Modifications should will only occur via draw-primitive, but we do need better locking
4619             switching to render-to-texture should remove the overhead though.
4620             */
4621             IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4622             IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4623             IWineD3DSurface_PreLoad(This->renderTarget);
4624             IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4625             IUnknown_Release(targetContainer);
4626         }
4627     }
4628     This->sceneEnded = TRUE;
4629     LEAVE_GL();
4630     return D3D_OK;
4631 }
4632
4633 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4634                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4635                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4636     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4637     IWineD3DSwapChain *swapChain = NULL;
4638     int i;
4639     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4640
4641     TRACE("(%p) Presenting the frame\n", This);
4642
4643     for(i = 0 ; i < swapchains ; i ++) {
4644
4645         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4646         TRACE("presentinng chain %d, %p\n", i, swapChain);
4647         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4648         IWineD3DSwapChain_Release(swapChain);
4649     }
4650
4651     return D3D_OK;
4652 }
4653
4654 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4655                                         DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4656     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4657
4658     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4659       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4660       when the depth-buffer format does not contain stencil buffer information, this method fails. */
4661     GLbitfield     glMask = 0;
4662     GLboolean      old_ztest;
4663     GLfloat        old_z_clear_value;
4664     GLint          old_stencil_clear_value;
4665     GLfloat        old_color_clear_value[4];
4666     unsigned int   i;
4667     CONST D3DRECT* curRect;
4668
4669     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4670           Count, pRects, Flags, Z, Stencil);
4671
4672     ENTER_GL();
4673
4674     glEnable(GL_SCISSOR_TEST);
4675     checkGLcall("glEnable GL_SCISSOR_TEST");
4676
4677     if (Count > 0 && pRects) {
4678         curRect = pRects;
4679     } else {
4680         curRect = NULL;
4681     }
4682
4683     /* Only set the values up once, as they are not changing */
4684     if (Flags & D3DCLEAR_STENCIL) {
4685         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4686         glClearStencil(Stencil);
4687         checkGLcall("glClearStencil");
4688         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4689         glStencilMask(0xFFFFFFFF);
4690     }
4691
4692     if (Flags & D3DCLEAR_ZBUFFER) {
4693         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4694         glDepthMask(GL_TRUE);
4695         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4696         glClearDepth(Z);
4697         checkGLcall("glClearDepth");
4698         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4699     }
4700
4701     if (Flags & D3DCLEAR_TARGET) {
4702         TRACE("Clearing screen with glClear to color %lx\n", Color);
4703         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4704         glClearColor(D3DCOLOR_R(Color),
4705                      D3DCOLOR_G(Color),
4706                      D3DCOLOR_B(Color),
4707                      D3DCOLOR_A(Color));
4708         checkGLcall("glClearColor");
4709
4710         /* Clear ALL colors! */
4711         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4712         glMask = glMask | GL_COLOR_BUFFER_BIT;
4713     }
4714
4715     /* Now process each rect in turn */
4716     for (i = 0; i < Count || i == 0; i++) {
4717
4718         if (curRect) {
4719             /* Note gl uses lower left, width/height */
4720             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4721                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4722                   curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4723                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4724             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4725                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4726             checkGLcall("glScissor");
4727         } else {
4728             glScissor(This->stateBlock->viewport.X,
4729                       (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - 
4730                       (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4731                       This->stateBlock->viewport.Width,
4732                       This->stateBlock->viewport.Height);
4733             checkGLcall("glScissor");
4734         }
4735
4736         /* Clear the selected rectangle (or full screen) */
4737         glClear(glMask);
4738         checkGLcall("glClear");
4739
4740         /* Step to the next rectangle */
4741         if (curRect) curRect = curRect + sizeof(D3DRECT);
4742     }
4743
4744     /* Restore the old values (why..?) */
4745     if (Flags & D3DCLEAR_STENCIL) {
4746         glClearStencil(old_stencil_clear_value);
4747         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4748     }
4749     if (Flags & D3DCLEAR_ZBUFFER) {
4750         glDepthMask(old_ztest);
4751         glClearDepth(old_z_clear_value);
4752     }
4753     if (Flags & D3DCLEAR_TARGET) {
4754         glClearColor(old_color_clear_value[0],
4755                      old_color_clear_value[1],
4756                      old_color_clear_value[2],
4757                      old_color_clear_value[3]);
4758         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4759                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4760                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4761                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4762     }
4763
4764     glDisable(GL_SCISSOR_TEST);
4765     checkGLcall("glDisable");
4766     LEAVE_GL();
4767
4768     return D3D_OK;
4769 }
4770
4771 /*****
4772  * Drawing functions
4773  *****/
4774 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4775                                                 UINT PrimitiveCount) {
4776
4777     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4778     This->stateBlock->streamIsUP = FALSE;
4779
4780     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4781                                debug_d3dprimitivetype(PrimitiveType),
4782                                StartVertex, PrimitiveCount);
4783     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4784                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4785
4786
4787     return D3D_OK;
4788 }
4789
4790 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4791 HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4792                                                            D3DPRIMITIVETYPE PrimitiveType,
4793                                                            INT baseVIndex, UINT minIndex,
4794                                                            UINT NumVertices, UINT startIndex, UINT primCount) {
4795
4796     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4797     UINT                 idxStride = 2;
4798     IWineD3DIndexBuffer *pIB;
4799     D3DINDEXBUFFER_DESC  IdxBufDsc;
4800
4801     pIB = This->stateBlock->pIndexData;
4802     This->stateBlock->streamIsUP = FALSE;
4803
4804     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
4805           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4806           minIndex, NumVertices, startIndex, baseVIndex, primCount);
4807
4808     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4809     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4810         idxStride = 2;
4811     } else {
4812         idxStride = 4;
4813     }
4814
4815     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4816                    idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4817
4818     return D3D_OK;
4819 }
4820
4821 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4822                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4823                                                     UINT VertexStreamZeroStride) {
4824     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4825
4826     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4827              debug_d3dprimitivetype(PrimitiveType),
4828              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4829
4830     /* release the stream source */
4831     if (This->stateBlock->streamSource[0] != NULL) {
4832         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4833     }
4834
4835     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4836     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4837     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4838     This->stateBlock->streamIsUP = TRUE;
4839
4840     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4841                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4842     /* stream zero settings set to null at end, as per the msdn
4843             http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4844     */
4845     This->stateBlock->streamStride[0] = 0;
4846     This->stateBlock->streamSource[0] = NULL;
4847
4848     /*stream zero settings set to null at end, as per the msdn */
4849     return D3D_OK;
4850 }
4851
4852 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4853                                                              UINT MinVertexIndex, UINT NumVertices,
4854                                                              UINT PrimitiveCount, CONST void* pIndexData,
4855                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4856                                                              UINT VertexStreamZeroStride) {
4857     int                 idxStride;
4858     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4859
4860     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4861              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4862              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4863              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4864
4865     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4866         idxStride = 2;
4867     } else {
4868         idxStride = 4;
4869     }
4870
4871     /* release the stream and index data */
4872     if (This->stateBlock->streamSource[0] != NULL) {
4873         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4874     }
4875     if (This->stateBlock->pIndexData) {
4876         IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
4877     }
4878
4879     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4880     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4881     This->stateBlock->streamIsUP = TRUE;
4882     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4883
4884     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4885     /* stream zero settings set to null at end as per the msdn
4886     http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawPrimitiveUP.asp
4887     */
4888
4889     /* stream zero settings set to null at end as per the msdn */
4890     This->stateBlock->streamSource[0] = NULL;
4891     This->stateBlock->streamStride[0] = 0;
4892
4893     return D3D_OK;
4894 }
4895
4896  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4897 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4898     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4899     HRESULT hr = D3D_OK;
4900     D3DRESOURCETYPE sourceType;
4901     D3DRESOURCETYPE destinationType;
4902     int i ,levels;
4903
4904     /* TODO: think about moving the code into IWineD3DBaseTexture  */
4905
4906     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4907
4908     /* verify that the source and destination textures aren't NULL */
4909     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4910         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning D3DERR_INVALIDCALL\n",
4911              This, pSourceTexture, pDestinationTexture);
4912         hr = D3DERR_INVALIDCALL;
4913     }
4914
4915     if (pSourceTexture == pDestinationTexture) {
4916         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning D3DERR_INVALIDCALL\n",
4917              This, pSourceTexture, pDestinationTexture);
4918         hr = D3DERR_INVALIDCALL;
4919     }
4920     /* Verify that the source and destination textures are the same type */
4921     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
4922     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4923
4924     if (sourceType != destinationType) {
4925         WARN("(%p) Sorce and destination types must match, returning D3DERR_INVALIDCALL\n",
4926              This);
4927         hr = D3DERR_INVALIDCALL;
4928     }
4929
4930     /* check that both textures have the identical numbers of levels  */
4931     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4932         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning D3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4933         hr = D3DERR_INVALIDCALL;
4934     }
4935
4936     if (D3D_OK == hr) {
4937
4938         /* Make sure that the destination texture is loaded */
4939         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4940
4941         /* Update every surface level of the texture */
4942         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4943
4944         switch (sourceType) {
4945         case D3DRTYPE_TEXTURE:
4946             {
4947                 IWineD3DSurface *srcSurface;
4948                 IWineD3DSurface *destSurface;
4949
4950                 for (i = 0 ; i < levels ; ++i) {
4951                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
4952                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4953                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4954                     IWineD3DSurface_Release(srcSurface);
4955                     IWineD3DSurface_Release(destSurface);
4956                     if (D3D_OK != hr) {
4957                         WARN("(%p) : Call to update surface failed\n", This);
4958                         return hr;
4959                     }
4960                 }
4961             }
4962             break;
4963         case D3DRTYPE_CUBETEXTURE:
4964             {
4965                 IWineD3DSurface *srcSurface;
4966                 IWineD3DSurface *destSurface;
4967                 D3DCUBEMAP_FACES faceType;
4968
4969                 for (i = 0 ; i < levels ; ++i) {
4970                     /* Update each cube face */
4971                     for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4972                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
4973                         if (D3D_OK != hr) {
4974                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4975                         } else {
4976                             TRACE("Got srcSurface %p\n", srcSurface);
4977                         }
4978                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4979                         if (D3D_OK != hr) {
4980                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4981                         } else {
4982                             TRACE("Got desrSurface %p\n", destSurface);
4983                         }
4984                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4985                         IWineD3DSurface_Release(srcSurface);
4986                         IWineD3DSurface_Release(destSurface);
4987                         if (D3D_OK != hr) {
4988                             WARN("(%p) : Call to update surface failed\n", This);
4989                             return hr;
4990                         }
4991                     }
4992                 }
4993             }
4994             break;
4995 #if 0 /* TODO: Add support for volume textures */
4996         case D3DRTYPE_VOLUMETEXTURE:
4997             {
4998                 IWineD3DVolume  srcVolume  = NULL;
4999                 IWineD3DSurface destVolume = NULL;
5000
5001                 for (i = 0 ; i < levels ; ++i) {
5002                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5003                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5004                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5005                     IWineD3DVolume_Release(srcSurface);
5006                     IWineD3DVolume_Release(destSurface);
5007                     if (D3D_OK != hr) {
5008                         WARN("(%p) : Call to update volume failed\n", This);
5009                         return hr;
5010                     }
5011                 }
5012             }
5013             break;
5014 #endif
5015         default:
5016             FIXME("(%p) : Unsupported source and destination type\n", This);
5017             hr = D3DERR_INVALIDCALL;
5018         }
5019     }
5020
5021     return hr;
5022 }
5023
5024 HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5025                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5026                                                 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
5027     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5028
5029     TRACE("(%p) : stub\n", This);
5030     return D3D_OK;
5031 }
5032 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5033     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5034     /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5035     *  NOTE It may be best to move the code into surface to occomplish this
5036     ****************************************/
5037
5038     WINED3DSURFACE_DESC surfaceDesc;
5039     unsigned int surfaceWidth, surfaceHeight;
5040     glDescriptor *targetGlDescription  = NULL;
5041     glDescriptor *surfaceGlDescription = NULL;
5042     IWineD3DSwapChainImpl *container = NULL;
5043     
5044     IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5045     IWineD3DSurface_GetGlDesc(pSurface,      &surfaceGlDescription);
5046     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5047
5048     surfaceDesc.Width  = &surfaceWidth;
5049     surfaceDesc.Height = &surfaceHeight;
5050     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5051    /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5052
5053     /* Ok, I may need to setup some kind of active swapchain reference on the device */
5054     IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5055     ENTER_GL();
5056     /* TODO: opengl Context switching for swapchains etc... */
5057     if (NULL != container  || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
5058         if (NULL != container  && (pRenderTarget == container->backBuffer)) {
5059             glReadBuffer(GL_BACK);
5060             vcheckGLcall("glReadBuffer(GL_BACK)");
5061         } else if ((NULL != container  && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
5062             glReadBuffer(GL_FRONT);
5063             vcheckGLcall("glReadBuffer(GL_FRONT)");
5064         } else if (pRenderTarget == This->depthStencilBuffer) {
5065             FIXME("Reading of depthstencil not yet supported\n");
5066         }
5067
5068         glReadPixels(surfaceGlDescription->target,
5069                     surfaceGlDescription->level,
5070                     surfaceWidth,
5071                     surfaceHeight,
5072                     surfaceGlDescription->glFormat,
5073                     surfaceGlDescription->glType,
5074                     (void *)IWineD3DSurface_GetData(pSurface));
5075         vcheckGLcall("glReadPixels(...)");
5076         if(NULL != container ){
5077             IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5078         }
5079     } else {
5080         IWineD3DBaseTexture *container;
5081         GLenum textureDimensions = GL_TEXTURE_2D;
5082
5083         if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5084             textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5085             IWineD3DBaseTexture_Release(container);
5086         }
5087         /* TODO: 2D -> Cube surface coppies etc.. */
5088         if (surfaceGlDescription->target != textureDimensions) {
5089             FIXME("(%p) : Texture dimension mismatch\n", This);
5090         }
5091         glEnable(textureDimensions);
5092         vcheckGLcall("glEnable(GL_TEXTURE_...)");
5093         /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5094         glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5095         vcheckGLcall("glBindTexture");
5096         glGetTexImage(surfaceGlDescription->target,
5097                         surfaceGlDescription->level,
5098                         surfaceGlDescription->glFormat,
5099                         surfaceGlDescription->glType,
5100                         (void *)IWineD3DSurface_GetData(pSurface));
5101         glDisable(textureDimensions);
5102         vcheckGLcall("glDisable(GL_TEXTURE_...)");
5103
5104     }
5105     LEAVE_GL();
5106     return D3D_OK;
5107 }
5108
5109 HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5110     IWineD3DSwapChain *swapChain;
5111     HRESULT hr;
5112     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5113     if(hr == D3D_OK) {
5114         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5115                 IWineD3DSwapChain_Release(swapChain);
5116     }
5117     return hr;
5118 }
5119
5120 HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5121     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5122     /* return a sensible default */
5123     *pNumPasses = 1;
5124     /* TODO: If the window is minimized then validate device should return something other than d3d_ok */
5125     FIXME("(%p) : stub\n", This);
5126     return D3D_OK;
5127 }
5128
5129 HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5130     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5131     int j;
5132     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5133     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5134         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5135         return D3DERR_INVALIDCALL;
5136     }
5137     for (j = 0; j < 256; ++j) {
5138         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5139         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5140         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5141         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5142     }
5143     TRACE("(%p) : returning\n", This);
5144     return D3D_OK;
5145 }
5146
5147 HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5148     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5149     int j;
5150     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5151     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5152         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5153         return D3DERR_INVALIDCALL;
5154     }
5155     for (j = 0; j < 256; ++j) {
5156         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5157         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5158         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5159         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5160     }
5161     TRACE("(%p) : returning\n", This);
5162     return D3D_OK;
5163 }
5164
5165 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5166     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5167     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5168     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5169         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5170         return D3DERR_INVALIDCALL;
5171     }
5172     /*TODO: stateblocks */
5173     This->currentPalette = PaletteNumber;
5174     TRACE("(%p) : returning\n", This);
5175     return D3D_OK;
5176 }
5177
5178 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5179     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5180     if (PaletteNumber == NULL) {
5181         WARN("(%p) : returning Invalid Call\n", This);
5182         return D3DERR_INVALIDCALL;
5183     }
5184     /*TODO: stateblocks */
5185     *PaletteNumber = This->currentPalette;
5186     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5187     return D3D_OK;
5188 }
5189
5190 HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5191     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5192     static BOOL showFixmes = TRUE;
5193     if (showFixmes) {
5194         FIXME("(%p) : stub\n", This);
5195         showFixmes = FALSE;
5196     }
5197
5198     This->softwareVertexProcessing = bSoftware;
5199     return D3D_OK;
5200 }
5201
5202
5203 BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5204     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5205     static BOOL showFixmes = TRUE;
5206     if (showFixmes) {
5207         FIXME("(%p) : stub\n", This);
5208         showFixmes = FALSE;
5209     }
5210     return This->softwareVertexProcessing;
5211 }
5212
5213
5214 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
5215     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5216     IWineD3DSwapChain *swapChain;
5217     HRESULT hr;
5218
5219     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5220
5221     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5222     if(hr == D3D_OK){
5223         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5224         IWineD3DSwapChain_Release(swapChain);
5225     }else{
5226         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5227     }
5228     return hr;
5229 }
5230
5231
5232 HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5233     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5234     static BOOL showfixmes = TRUE;
5235     if(nSegments != 0.0f) {
5236         if( showfixmes) {
5237             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5238             showfixmes = FALSE;
5239         }
5240     }
5241     return D3D_OK;
5242 }
5243
5244 float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5245     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5246     static BOOL showfixmes = TRUE;
5247     if( showfixmes) {
5248         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5249         showfixmes = FALSE;
5250     }
5251     return 0.0f;
5252 }
5253
5254 HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5255     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5256     /** TODO: remove casts to IWineD3DSurfaceImpl
5257      *       NOTE: move code to surface to accomplish this
5258       ****************************************/
5259     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5260     int srcWidth, srcHeight;
5261     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5262     WINED3DFORMAT destFormat, srcFormat;
5263     UINT          destSize;
5264     int destLeft, destTop;
5265     D3DPOOL       srcPool, destPool;
5266     int offset    = 0;
5267     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5268     glDescriptor *glDescription = NULL;
5269     GLenum textureDimensions = GL_TEXTURE_2D;
5270     IWineD3DBaseTexture *baseTexture;
5271
5272     WINED3DSURFACE_DESC  winedesc;
5273
5274     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5275     memset(&winedesc, 0, sizeof(winedesc));
5276     winedesc.Width  = &srcSurfaceWidth;
5277     winedesc.Height = &srcSurfaceHeight;
5278     winedesc.Pool   = &srcPool;
5279     winedesc.Format = &srcFormat;
5280
5281     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5282
5283     winedesc.Width  = &destSurfaceWidth;
5284     winedesc.Height = &destSurfaceHeight;
5285     winedesc.Pool   = &destPool;
5286     winedesc.Format = &destFormat;
5287     winedesc.Size   = &destSize;
5288
5289     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5290
5291     if(srcPool != D3DPOOL_SYSTEMMEM  || destPool != D3DPOOL_DEFAULT){
5292         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning D3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5293         return D3DERR_INVALIDCALL;
5294     }
5295
5296     if (destFormat == WINED3DFMT_UNKNOWN) {
5297         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5298         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5299
5300         /* Get the update surface description */
5301         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5302     }
5303
5304     /* Make sure the surface is loaded and up to date */
5305     IWineD3DSurface_PreLoad(pDestinationSurface);
5306
5307     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5308
5309     ENTER_GL();
5310
5311     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5312     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5313     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
5314     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5315     destTop    = pDestPoint  ? pDestPoint->y : 0;
5316
5317
5318     /* This function doesn't support compressed textures
5319     the pitch is just bytesPerPixel * width */
5320     if(srcWidth != srcSurfaceWidth  || (pSourceRect != NULL && pSourceRect->left != 0) ){
5321         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5322         offset   += pSourceRect->left * pSrcSurface->bytesPerPixel;
5323         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5324     }
5325     /* TODO DXT formats */
5326
5327     if(pSourceRect != NULL && pSourceRect->top != 0){
5328        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5329     }
5330     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5331     ,This
5332     ,glDescription->level
5333     ,destLeft
5334     ,destTop
5335     ,srcWidth
5336     ,srcHeight
5337     ,glDescription->glFormat
5338     ,glDescription->glType
5339     ,IWineD3DSurface_GetData(pSourceSurface)
5340     );
5341
5342     /* Sanity check */
5343     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5344
5345         /* need to lock the surface to get the data */
5346         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5347     }
5348
5349     /* TODO: Cube and volume support */
5350     if(rowoffset != 0){
5351         /* not a whole row so we have to do it a line at a time */
5352         int j;
5353
5354         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5355         unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5356
5357         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5358
5359                 glTexSubImage2D(glDescription->target
5360                     ,glDescription->level
5361                     ,destLeft
5362                     ,j
5363                     ,srcWidth
5364                     ,1
5365                     ,glDescription->glFormat
5366                     ,glDescription->glType
5367                     ,data /* could be quicker using */
5368                 );
5369             data += rowoffset;
5370         }
5371
5372     } else { /* Full width, so just write out the whole texture */
5373
5374         if (WINED3DFMT_DXT1 == destFormat ||
5375             WINED3DFMT_DXT2 == destFormat ||
5376             WINED3DFMT_DXT3 == destFormat ||
5377             WINED3DFMT_DXT4 == destFormat ||
5378             WINED3DFMT_DXT5 == destFormat) {
5379             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5380                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5381                     /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
5382                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5383                 } if (destFormat != srcFormat) {
5384                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5385                 } else {
5386                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5387                                                         glDescription->level,
5388                                                         glDescription->glFormatInternal,
5389                                                         srcWidth,
5390                                                         srcHeight,
5391                                                         0,
5392                                                         destSize,
5393                                                         IWineD3DSurface_GetData(pSourceSurface));
5394                 }
5395             } else {
5396                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5397             }
5398
5399
5400         } else {
5401             if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5402
5403                 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5404                 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5405                 data returned by GetData non-power2 width/height with hardware non-power2
5406                 pow2Width/height are set to surface width height, repacking isn't needed so it
5407                 doesn't matter which function gets called. */
5408                 glTexSubImage2D(glDescription->target
5409                         ,glDescription->level
5410                         ,destLeft
5411                         ,destTop
5412                         ,srcWidth
5413                         ,srcHeight
5414                         ,glDescription->glFormat
5415                         ,glDescription->glType
5416                         ,IWineD3DSurface_GetData(pSourceSurface)
5417                     );
5418             } else {
5419
5420                 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5421                 glTexSubImage2D(glDescription->target
5422                     ,glDescription->level
5423                     ,destLeft
5424                     ,destTop
5425                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5426                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5427                     ,glDescription->glFormat
5428                     ,glDescription->glType
5429                     ,IWineD3DSurface_GetData(pSourceSurface)
5430                 );
5431             }
5432
5433         }
5434      }
5435     checkGLcall("glTexSubImage2D");
5436
5437     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5438      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5439      * surface bigger than it needs to be hmm.. */
5440     if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5441         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5442         IWineD3DBaseTexture_Release(baseTexture);
5443     }
5444
5445     glDisable(textureDimensions); /* This needs to be managed better.... */
5446     LEAVE_GL();
5447
5448     return D3D_OK;
5449 }
5450
5451 /* Used by DirectX 8 */
5452 HRESULT  WINAPI  IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
5453                                                 IWineD3DSurface* pSourceSurface,      CONST RECT* pSourceRectsArray, UINT cRects,
5454                                                 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
5455
5456     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
5457     HRESULT              hr = D3D_OK;
5458     WINED3DFORMAT        srcFormat, destFormat;
5459     UINT                 srcWidth,  destWidth;
5460     UINT                 srcHeight, destHeight;
5461     UINT                 srcSize;
5462     WINED3DSURFACE_DESC  winedesc;
5463
5464     TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
5465           pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
5466
5467
5468     /* Check that the source texture is in D3DPOOL_SYSTEMMEM and the destination texture is in D3DPOOL_DEFAULT */
5469     memset(&winedesc, 0, sizeof(winedesc));
5470
5471     winedesc.Format = &srcFormat;
5472     winedesc.Width  = &srcWidth;
5473     winedesc.Height = &srcHeight;
5474     winedesc.Size   = &srcSize;
5475     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5476
5477     winedesc.Format = &destFormat;
5478     winedesc.Width  = &destWidth;
5479     winedesc.Height = &destHeight;
5480     winedesc.Size   = NULL;
5481     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5482
5483     /* Check that the source and destination formats match */
5484     if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
5485         WARN("(%p) source %p format must match the dest %p format, returning D3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
5486         return D3DERR_INVALIDCALL;
5487     } else if (WINED3DFMT_UNKNOWN == destFormat) {
5488         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5489         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5490         destFormat = srcFormat;
5491     }
5492
5493     /* Quick if complete copy ... */
5494     if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
5495
5496         if (srcWidth == destWidth && srcHeight == destHeight) {
5497             D3DLOCKED_RECT lrSrc;
5498             D3DLOCKED_RECT lrDst;
5499             IWineD3DSurface_LockRect(pSourceSurface,      &lrSrc, NULL, D3DLOCK_READONLY);
5500             IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
5501             TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
5502
5503             memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
5504
5505             IWineD3DSurface_UnlockRect(pSourceSurface);
5506             IWineD3DSurface_UnlockRect(pDestinationSurface);
5507             TRACE("Unlocked src and dst\n");
5508
5509         } else {
5510
5511             FIXME("Wanted to copy all surfaces but size not compatible, returning D3DERR_INVALIDCALL\n");
5512             hr = D3DERR_INVALIDCALL;
5513          }
5514
5515     } else {
5516
5517         if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
5518
5519             int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
5520             unsigned int i;
5521
5522             /* Copy rect by rect */
5523             for (i = 0; i < cRects; ++i) {
5524                 CONST RECT*  r = &pSourceRectsArray[i];
5525                 CONST POINT* p = &pDestPointsArray[i];
5526                 int copyperline;
5527                 int j;
5528                 D3DLOCKED_RECT lrSrc;
5529                 D3DLOCKED_RECT lrDst;
5530                 RECT dest_rect;
5531
5532                 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
5533                 if (srcFormat == WINED3DFMT_DXT1) {
5534                     copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
5535                 } else {
5536                     copyperline = ((r->right - r->left) * bytesPerPixel);
5537                 }
5538
5539                 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, D3DLOCK_READONLY);
5540                 dest_rect.left  = p->x;
5541                 dest_rect.top   = p->y;
5542                 dest_rect.right = p->x + (r->right - r->left);
5543                 dest_rect.bottom= p->y + (r->bottom - r->top);
5544                 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
5545                 TRACE("Locked src and dst\n");
5546
5547                 /* Find where to start */
5548                 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
5549                     memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
5550                 }
5551                 IWineD3DSurface_UnlockRect(pSourceSurface);
5552                 IWineD3DSurface_UnlockRect(pDestinationSurface);
5553                 TRACE("Unlocked src and dst\n");
5554             }
5555         } else {
5556             FIXME("Wanted to copy partial surfaces not implemented, returning D3DERR_INVALIDCALL\n");
5557             hr = D3DERR_INVALIDCALL;
5558         }
5559     }
5560
5561     return hr;
5562 }
5563
5564 /* Implementation details at http://developer.nvidia.com/attach/6494
5565 and
5566 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5567 hmm.. no longer supported use
5568 OpenGL evaluators or  tessellate surfaces within your application.
5569 */
5570
5571 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5572 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5573     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5574     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5575     FIXME("(%p) : Stub\n", This);
5576     return D3D_OK;
5577
5578 }
5579
5580 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5581 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5582     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5583     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5584     FIXME("(%p) : Stub\n", This);
5585     return D3D_OK;
5586 }
5587
5588 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5589     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5590     TRACE("(%p) Handle(%d)\n", This, Handle);
5591     FIXME("(%p) : Stub\n", This);
5592     return D3D_OK;
5593 }
5594
5595 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5596     /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5597     fill a surface with a block of color!  */
5598     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5599     /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5600     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5601     IWineD3DSwapChainImpl *container = NULL;
5602     BOOL isRenderTarget = FALSE;
5603     unsigned int width, height;
5604     unsigned int top, left;
5605     unsigned int u, v;
5606     DWORD       *data;
5607     TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5608
5609     if (surface->resource.pool != D3DPOOL_DEFAULT) {
5610         FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5611         return D3DERR_INVALIDCALL;
5612     }
5613
5614     /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5615     if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5616         if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5617             /* TODO: make sure we set everything back to the way it was, and context management!
5618                 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5619                 vcheckGLcall("glIntegerv");
5620                 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5621                 vcheckGLcall("glIntegerv");
5622             */
5623             TRACE("Color fill to render targets may cause some graphics issues\n");
5624             if (pSurface == container->frontBuffer) {
5625                 glDrawBuffer(GL_FRONT);
5626             } else {
5627                 glDrawBuffer(GL_BACK);
5628             }
5629         } else {
5630             if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5631                 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface, surface->resource.usage);
5632             } else {
5633                 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5634             }
5635             if (container != NULL) {
5636                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5637             }
5638             /* we can use GL_STENCIL_INDEX etc...*/
5639             return D3D_OK;
5640         }
5641         if (container != NULL) {
5642             IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5643         }
5644         isRenderTarget = TRUE;
5645     }
5646     /* TODO: drawing to GL_FRONT and GL_BACK */
5647     /* TODO: see if things can be speeded up by using the correct
5648      * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5649     if (pRect == NULL) {
5650         top    = 0;
5651         left   = 0;
5652         width  = surface->currentDesc.Width;
5653         height = surface->currentDesc.Height;
5654     } else {
5655         left   = pRect->x1;
5656         top    = pRect->y1;
5657         width  = pRect->x2 - left;
5658         height = pRect->y2 - top;
5659     }
5660
5661     data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5662     /* Create a 'line' of color color, in the correct format for the surface */
5663     for (u = 0 ; u < width ; u ++) {
5664             data[u] = color;
5665     }
5666
5667     ENTER_GL();
5668     if (isRenderTarget == FALSE) {
5669         glDescriptor *glDesc;
5670         IWineD3DSurface_PreLoad(pSurface);
5671
5672         /* draw a block of the coloured line on the sufrace */
5673         IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5674         for (v = 0 ; v< height;v++) {
5675             glTexSubImage2D(glDesc->target
5676                             ,glDesc->level /* level */
5677                             ,left
5678                             ,top + v
5679                             ,width
5680                             ,1 /* height */
5681                             ,GL_RGBA
5682                             ,GL_UNSIGNED_BYTE
5683                             ,data
5684                             );
5685         }
5686         checkGLcall("glTexSubImage2D");
5687         /* clean up */
5688         glDisable(glDesc->target);
5689     } else {
5690         /** FIXME: Using GLClear may be faster **/
5691         glRasterPos2i(left, top);
5692         glPixelZoom((float)width ,(float)height);
5693         glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5694         checkGLcall("glDrawPixels");
5695     }
5696     HeapFree(GetProcessHeap(), 0, data);
5697     LEAVE_GL();
5698     return D3D_OK;
5699
5700 }
5701
5702 /* rendertarget and deptth stencil functions */
5703 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5704     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5705
5706     /* FIXME: Implelent RenderTargetIndex >0 */
5707     if(RenderTargetIndex > 0)
5708         FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5709
5710     *ppRenderTarget = This->renderTarget;
5711     TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5712     /* Note inc ref on returned surface */
5713     if(*ppRenderTarget != NULL)
5714         IWineD3DSurface_AddRef(*ppRenderTarget);
5715     return D3D_OK;
5716 }
5717
5718 HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5719     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5720     *ppZStencilSurface = This->depthStencilBuffer;
5721     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5722
5723     if(*ppZStencilSurface != NULL) {
5724         /* Note inc ref on returned surface */
5725         IWineD3DSurface_AddRef(*ppZStencilSurface);
5726     }
5727     return D3D_OK;
5728 }
5729
5730 /* internal static helper functions */
5731 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5732                                                 IWineD3DSurface *RenderSurface);
5733
5734 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5735     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5736     HRESULT  hr = D3D_OK;
5737     WINED3DVIEWPORT viewport;
5738
5739     TRACE("(%p) Swapping rendertarget\n",This);
5740     if (RenderTargetIndex > 0) {
5741         FIXME("(%p) Render targets other than the first are not supported\n",This);
5742         RenderTargetIndex = 0;
5743     }
5744
5745     /* MSDN says that null disables the render target
5746     but a device must always be associated with a render target
5747     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5748
5749     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5750     for more details
5751     */
5752     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5753         FIXME("Trying to set render target 0 to NULL\n");
5754         return D3DERR_INVALIDCALL;
5755     }
5756     /* TODO: replace Impl* usage with interface usage */
5757     if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5758         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);
5759         return D3DERR_INVALIDCALL;
5760     }
5761     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5762      *        builds, but I think wine counts as a 'debug' build for now.
5763       ******************************/
5764     /* If we are trying to set what we already have, don't bother */
5765     if (pRenderTarget == This->renderTarget) {
5766         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5767     } else {
5768         /* Otherwise, set the render target up */
5769
5770         if (FALSE == This->sceneEnded) {
5771             IWineD3DDevice_EndScene(iface);
5772         }
5773         TRACE("clearing renderer\n");
5774         /* IWineD3DDeviceImpl_CleanRender(iface); */
5775         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5776         depending on the renter target implementation being used.
5777         A shared context implementation will share all buffers between all rendertargets (including swapchains),
5778         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5779         stencil buffer and incure an extra memory overhead */
5780         hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5781     }
5782
5783     if (SUCCEEDED(hr)) {
5784         /* Finally, reset the viewport as the MSDN states. */
5785         /* TODO: Replace impl usage */
5786         viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5787         viewport.Width  = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5788         viewport.X      = 0;
5789         viewport.Y      = 0;
5790         viewport.MaxZ   = 1.0f;
5791         viewport.MinZ   = 0.0f;
5792         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5793     } else {
5794         FIXME("Unknown error setting the render target\n");
5795     }
5796     This->sceneEnded = FALSE;
5797     return hr;
5798 }
5799
5800 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5801     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5802     HRESULT  hr = D3D_OK;
5803     IWineD3DSurface *tmp;
5804
5805     TRACE("(%p) Swapping z-buffer\n",This);
5806
5807     if (pNewZStencil == This->stencilBufferTarget) {
5808         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5809     } else {
5810         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5811         * depending on the renter target implementation being used.
5812         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5813         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5814         * stencil buffer and incure an extra memory overhead
5815          ******************************************************/
5816
5817
5818         tmp = This->stencilBufferTarget;
5819         This->stencilBufferTarget = pNewZStencil;
5820         /* should we be calling the parent or the wined3d surface? */
5821         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5822         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5823         hr = D3D_OK;
5824         /** TODO: glEnable/glDisable on depth/stencil    depending on
5825          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
5826           **********************************************************/
5827     }
5828
5829     return hr;
5830 }
5831
5832
5833 #ifdef GL_VERSION_1_3
5834 /* Internal functions not in DirectX */
5835  /** TODO: move this off to the opengl context manager
5836  *(the swapchain doesn't need to know anything about offscreen rendering!)
5837   ****************************************************/
5838
5839 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5840 {
5841     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5842
5843     TRACE("(%p), %p\n", This, swapchain);
5844
5845     if (swapchain->win != swapchain->drawable) {
5846         /* Set everything back the way it ws */
5847         swapchain->render_ctx = swapchain->glCtx;
5848         swapchain->drawable   = swapchain->win;
5849     }
5850     return D3D_OK;
5851 }
5852
5853 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5854 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5855     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5856     int i;
5857     unsigned int width;
5858     unsigned int height;
5859     WINED3DFORMAT format;
5860     WINED3DSURFACE_DESC surfaceDesc;
5861     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5862     surfaceDesc.Width  = &width;
5863     surfaceDesc.Height = &height;
5864     surfaceDesc.Format = &format;
5865     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5866     *context = NULL;
5867     /* I need a get width/height function (and should do something with the format) */
5868     for (i = 0; i < CONTEXT_CACHE; ++i) {
5869         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5870         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5871         the pSurface can be set to 0 allowing it to be reused from cache **/
5872         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5873           && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5874             *context = &This->contextCache[i];
5875             break;
5876         }
5877         if (This->contextCache[i].Width == 0) {
5878             This->contextCache[i].pSurface = pSurface;
5879             This->contextCache[i].Width    = width;
5880             This->contextCache[i].Height   = height;
5881             *context = &This->contextCache[i];
5882             break;
5883         }
5884     }
5885     if (i == CONTEXT_CACHE) {
5886         int minUsage = 0x7FFFFFFF; /* MAX_INT */
5887         glContext *dropContext = 0;
5888         for (i = 0; i < CONTEXT_CACHE; i++) {
5889             if (This->contextCache[i].usedcount < minUsage) {
5890                 dropContext = &This->contextCache[i];
5891                 minUsage = This->contextCache[i].usedcount;
5892             }
5893         }
5894         /* clean up the context (this doesn't work for ATI at the moment */
5895 #if 0
5896         glXDestroyContext(swapchain->display, dropContext->context);
5897         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5898 #endif
5899         FIXME("Leak\n");
5900         dropContext->Width = 0;
5901         dropContext->pSurface = pSurface;
5902         *context = dropContext;
5903     } else {
5904         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5905           for (i = 0; i < CONTEXT_CACHE; i++) {
5906              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5907           }
5908         }
5909     }
5910     if (*context != NULL)
5911         return D3D_OK;
5912     else
5913         return E_OUTOFMEMORY;
5914 }
5915 #endif
5916
5917 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5918 * the functionality needs splitting up so that we don't do more than we should do.
5919 * this only seems to impact performance a little.
5920  ******************************/
5921 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5922                                                IWineD3DSurface *RenderSurface) {
5923     HRESULT ret =  D3DERR_INVALIDCALL;
5924
5925     /**
5926     * Currently only active for GLX >= 1.3
5927     * for others versions we'll have to use GLXPixmaps
5928     *
5929     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5930     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5931     * so only check OpenGL version
5932     * ..........................
5933     * I don't believe that it is a problem with NVidia headers,
5934     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5935     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5936     * ATI Note:
5937     * Your application will report GLX version 1.2 on glXQueryVersion.
5938     * However, it is safe to call the GLX 1.3 functions as described below.
5939     */
5940 #if defined(GL_VERSION_1_3)
5941
5942     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5943     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5944     IWineD3DSurface *tmp;
5945     /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5946     GLXFBConfig* cfgs = NULL;
5947     int nCfgs = 0;
5948     int attribs[256];
5949     int nAttribs = 0;
5950     IWineD3DSwapChain     *currentSwapchain;
5951     IWineD3DSwapChainImpl *swapchain;
5952     /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5953     * but switch them off if the StencilSurface is set to NULL
5954     ** *********************************************************/
5955     D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5956     D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5957
5958     /**TODO:
5959         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5960         it StencilSurface != NULL && zBufferTarget == NULL switch it on
5961     */
5962
5963 #define PUSH1(att)        attribs[nAttribs++] = (att);
5964 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5965
5966     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5967
5968     /** TODO: remove the reff to Impl (context manager should fix this!) **/
5969     IWineD3DSwapChainImpl *impSwapChain;
5970     IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5971     if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5972         ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5973     }
5974
5975     ENTER_GL();
5976
5977     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5978     PUSH2(GLX_X_RENDERABLE,  TRUE);
5979     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
5980     TRACE("calling makeglcfg\n");
5981     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5982     PUSH1(None);
5983
5984     TRACE("calling chooseFGConfig\n");
5985     cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5986                                                      attribs, &nCfgs);
5987
5988     if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5989         /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5990            why we failed and only show this message once! */
5991         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"); /**/
5992         nAttribs = 0;
5993         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5994        /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
5995         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
5996         PUSH2(GLX_DOUBLEBUFFER, FALSE);
5997         TRACE("calling makeglcfg\n");
5998         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5999         PUSH1(None);
6000         cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
6001                                                         attribs, &nCfgs);
6002     }
6003
6004     if (NULL != cfgs) {
6005 #ifdef EXTRA_TRACES
6006         int i;
6007         for (i = 0; i < nCfgs; ++i) {
6008             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6009             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6010             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6011         }
6012
6013         if (NULL != This->renderTarget) {
6014             glFlush();
6015             vcheckGLcall("glFlush");
6016             /** This is only useful if the old render target was a swapchain,
6017             * we need to supercede this with a function that displays
6018             * the current buffer on the screen. This is easy to do in glx1.3 but
6019             * we need to do copy-write pixels in glx 1.2.
6020             ************************************************/
6021             glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
6022
6023             printf("Hit Enter to get next frame ...\n");
6024             getchar();
6025         }
6026 #endif
6027     }
6028
6029     if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK) {
6030         /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6031         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
6032     }
6033
6034     /**
6035     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6036     *  renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6037      **********************************************************************/
6038     if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
6039         /* We also need to make sure that the lights &co are also in the context of the swapchains */
6040         /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6041         TRACE("making swapchain active\n");
6042         if (RenderSurface != This->renderTarget) {
6043             if (RenderSurface ==  swapchain->backBuffer) {
6044             } else {
6045                 /* This could be flagged so that some operations work directly with the front buffer */
6046                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
6047             }
6048             if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
6049             == False) {
6050                 TRACE("Error in setting current context: context %p drawable %ld !\n",
6051                        impSwapChain->glCtx, impSwapChain->win);
6052             }
6053
6054             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6055         }
6056         checkGLcall("glXMakeContextCurrent");
6057
6058         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
6059     }
6060     else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
6061
6062         /** ********************************************************************
6063         * This is a quickly hacked out implementation of offscreen textures.
6064         * It will work in most cases but there may be problems if the client
6065         * modifies the texture directly, or expects the contents of the rendertarget
6066         * to be persistent.
6067         *
6068         * There are some real speed vs compatibility issues here:
6069         *    we should really use a new context for every texture, but that eats ram.
6070         *    we should also be restoring the texture to the pbuffer but that eats CPU
6071         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6072         *    but if this means reusing the display backbuffer then we need to make sure that
6073         *    states are correctly preserved.
6074         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6075         * and gain a good performance increase at the cost of compatibility.
6076         * I would suggest that, when this is the case, a user configurable flag be made
6077         * available, allowing the user to choose the best emulated experience for them.
6078          *********************************************************************/
6079
6080         XVisualInfo *visinfo;
6081         glContext   *newContext;
6082
6083         /* Here were using a shared context model */
6084         if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6085             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6086         }
6087
6088         /* If the context doesn't exist then create a new one */
6089         /* TODO: This should really be part of findGlContext */
6090         if (NULL == newContext->context) {
6091
6092             TRACE("making new buffer\n");
6093             nAttribs = 0;
6094             PUSH2(GLX_PBUFFER_WIDTH,  newContext->Width);
6095             PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
6096             PUSH1(None);
6097
6098             newContext->drawable  = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
6099
6100             /** ****************************************
6101             *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6102             *they note:
6103             *   In future releases, we may provide the calls glXCreateNewContext,
6104             *   glXQueryDrawable and glXMakeContextCurrent.
6105             *    so until then we have to use glXGetVisualFromFBConfig &co..
6106             ********************************************/
6107
6108
6109             visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
6110             if (!visinfo) {
6111                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6112             } else {
6113                 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx,  GL_TRUE);
6114                 XFree(visinfo);
6115             }
6116         }
6117         if (NULL == newContext || NULL == newContext->context) {
6118             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6119         } else {
6120             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6121             if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
6122                 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
6123             }
6124
6125             /* Clean up the old context */
6126             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
6127             /* Set the current context of the swapchain to the new context */
6128             impSwapChain->drawable   = newContext->drawable;
6129             impSwapChain->render_ctx = newContext->context;
6130         }
6131     }
6132
6133 #if 1 /* Apply the stateblock to the new context
6134 FIXME: This is a bit of a hack, each context should know it's own state,
6135 the directX current directX state should then be applied to the context */
6136     {
6137         BOOL oldRecording;
6138         IWineD3DStateBlockImpl *oldUpdateStateBlock;
6139         oldUpdateStateBlock = This->updateStateBlock;
6140         oldRecording= This->isRecordingState;
6141         This->isRecordingState = FALSE;
6142         This->updateStateBlock = This->stateBlock;
6143         IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6144
6145         This->isRecordingState = oldRecording;
6146         This->updateStateBlock = oldUpdateStateBlock;
6147     }
6148 #endif
6149
6150
6151     /* clean up the current rendertargets swapchain (if it belonged to one) */
6152     if (currentSwapchain != NULL) {
6153         IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
6154     }
6155
6156     /* Were done with the opengl context management, setup the rendertargets */
6157
6158     tmp = This->renderTarget;
6159     This->renderTarget = RenderSurface;
6160     IWineD3DSurface_AddRef(This->renderTarget);
6161     IWineD3DSurface_Release(tmp);
6162
6163
6164
6165     {
6166         DWORD value;
6167         /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
6168         /* Check that the container is not a swapchain member */
6169
6170         IWineD3DSwapChain *tmpSwapChain;
6171         if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
6172             This->renderUpsideDown = TRUE;
6173         }else{
6174             This->renderUpsideDown = FALSE;
6175             IWineD3DSwapChain_Release(tmpSwapChain);
6176         }
6177         /* Force updating the cull mode */
6178         TRACE("setting render state\n");
6179         IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
6180         IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
6181
6182         /* Force updating projection matrix */
6183         This->last_was_rhw = FALSE;
6184         This->proj_valid = FALSE;
6185     }
6186
6187     ret = D3D_OK;
6188
6189     if (cfgs != NULL) {
6190         XFree(cfgs);
6191     } else {
6192         ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
6193             debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6194     }
6195
6196 #undef PUSH1
6197 #undef PUSH2
6198     if ( NULL != impSwapChain) {
6199         IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
6200     }
6201     LEAVE_GL();
6202
6203 #endif
6204     return ret;
6205 }
6206
6207 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6208                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6209     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6210     /* TODO: the use of Impl is deprecated. */
6211     /* some basic validation checks */
6212     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6213
6214     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6215
6216     if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6217       ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6218       return D3DERR_INVALIDCALL;
6219     }
6220     if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
6221       ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
6222       return D3DERR_INVALIDCALL;
6223     }
6224     /* TODO: make the cursor 'real' */
6225
6226     This->xHotSpot = XHotSpot;
6227     This->yHotSpot = YHotSpot;
6228
6229     return D3D_OK;
6230 }
6231
6232 void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6233     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6234     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6235
6236     This->xScreenSpace = XScreenSpace;
6237     This->yScreenSpace = YScreenSpace;
6238
6239     return;
6240
6241 }
6242
6243 BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6244     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6245     TRACE("(%p) : visible(%d)\n", This, bShow);
6246
6247     This->bCursorVisible = bShow;
6248
6249     return D3D_OK;
6250 }
6251
6252 HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6253     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6254     TRACE("(%p) : state (%lu)\n", This, This->state);
6255     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6256     switch (This->state) {
6257     case D3D_OK:
6258         return D3D_OK;
6259     case D3DERR_DEVICELOST:
6260         {
6261             ResourceList *resourceList  = This->resources;
6262             while (NULL != resourceList) {
6263                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == D3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6264                 return D3DERR_DEVICENOTRESET;
6265                 resourceList = resourceList->next;
6266             }
6267             return D3DERR_DEVICELOST;
6268         }
6269     case D3DERR_DRIVERINTERNALERROR:
6270         return D3DERR_DRIVERINTERNALERROR;
6271     }
6272
6273     /* Unknown state */
6274     return D3DERR_DRIVERINTERNALERROR;
6275 }
6276
6277
6278 HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6279     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6280     /** FIXME: Resource tracking needs to be done,
6281     * The closes we can do to this is set the priorities of all managed textures low
6282     * and then reset them.
6283      ***********************************************************/
6284     FIXME("(%p) : stub\n", This);
6285     return D3D_OK;
6286 }
6287
6288 HRESULT  WINAPI  IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
6289     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6290     /** FIXME: Resource trascking needs to be done.
6291     * in effect this pulls all non only default
6292     * textures out of video memory and deletes all glTextures (glDeleteTextures)
6293     * and should clear down the context and set it up according to pPresentationParameters
6294      ***********************************************************/
6295     FIXME("(%p) : stub\n", This);
6296     return D3D_OK;
6297 }
6298
6299 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6300     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6301     /** FIXME: always true at the moment **/
6302     if(bEnableDialogs == FALSE) {
6303         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6304     }
6305     return D3D_OK;
6306 }
6307
6308
6309 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
6310     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6311
6312     FIXME("(%p) : stub\n", This);
6313     /* Setup some reasonable defaults */
6314     pParameters->AdapterOrdinal = 0; /* always for now */
6315     pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
6316     pParameters->hFocusWindow = 0;
6317     pParameters->BehaviorFlags =0;
6318     return D3D_OK;
6319 }
6320
6321 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
6322     IWineD3DSwapChain *swapchain;
6323     HRESULT hrc = D3D_OK;
6324
6325     TRACE("Relaying  to swapchain\n");
6326
6327     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6328         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
6329         IWineD3DSwapChain_Release(swapchain);
6330     }
6331     return;
6332 }
6333
6334 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
6335     IWineD3DSwapChain *swapchain;
6336     HRESULT hrc = D3D_OK;
6337
6338     TRACE("Relaying  to swapchain\n");
6339
6340     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
6341         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6342         IWineD3DSwapChain_Release(swapchain);
6343     }
6344     return;
6345 }
6346
6347
6348 /** ********************************************************
6349 *   Notification functions
6350 ** ********************************************************/
6351 /** This function must be called in the release of a resource when ref == 0,
6352 * the contents of resource must still be correct,
6353 * any handels to other resource held by the caller must be closed
6354 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6355  *****************************************************/
6356 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6357     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6358     ResourceList* resourceList;
6359
6360     TRACE("(%p) : resource %p\n", This, resource);
6361 #if 0
6362     EnterCriticalSection(&resourceStoreCriticalSection);
6363 #endif
6364     /* add a new texture to the frot of the linked list */
6365     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6366     resourceList->resource = resource;
6367
6368     /* Get the old head */
6369     resourceList->next = This->resources;
6370
6371     This->resources = resourceList;
6372     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6373
6374 #if 0
6375     LeaveCriticalSection(&resourceStoreCriticalSection);
6376 #endif
6377     return;
6378 }
6379
6380 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6381     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6382     ResourceList* resourceList = NULL;
6383     ResourceList* previousResourceList = NULL;
6384     
6385     TRACE("(%p) : resource %p\n", This, resource);
6386
6387 #if 0
6388     EnterCriticalSection(&resourceStoreCriticalSection);
6389 #endif
6390     resourceList = This->resources;
6391
6392     while (resourceList != NULL) {
6393         if(resourceList->resource == resource) break;
6394         previousResourceList = resourceList;
6395         resourceList = resourceList->next;
6396     }
6397
6398     if (resourceList == NULL) {
6399         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6400 #if 0
6401         LeaveCriticalSection(&resourceStoreCriticalSection);
6402 #endif
6403         return;
6404     } else {
6405             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6406     }
6407     /* make sure we don't leave a hole in the list */
6408     if (previousResourceList != NULL) {
6409         previousResourceList->next = resourceList->next;
6410     } else {
6411         This->resources = resourceList->next;
6412     }
6413
6414 #if 0
6415     LeaveCriticalSection(&resourceStoreCriticalSection);
6416 #endif
6417     return;
6418 }
6419
6420
6421 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6422     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6423     int counter;
6424
6425     TRACE("(%p) : resource %p\n", This, resource);
6426     switch(IWineD3DResource_GetType(resource)){
6427         case D3DRTYPE_SURFACE:
6428         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6429         break;
6430         case D3DRTYPE_TEXTURE:
6431         case D3DRTYPE_CUBETEXTURE:
6432         case D3DRTYPE_VOLUMETEXTURE:
6433                 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
6434                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6435                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6436                         This->stateBlock->textures[counter] = NULL;
6437                     }
6438                     if (This->updateStateBlock != This->stateBlock ){
6439                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6440                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6441                             This->updateStateBlock->textures[counter] = NULL;
6442                         }
6443                     }
6444                 }
6445         break;
6446         case D3DRTYPE_VOLUME:
6447         /* TODO: nothing really? */
6448         break;
6449         case D3DRTYPE_VERTEXBUFFER:
6450         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6451         {
6452             int streamNumber;
6453             TRACE("Cleaning up stream pointers\n");
6454
6455             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6456                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6457                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6458                 */
6459                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6460                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6461                         FIXME("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
6462                         This->updateStateBlock->streamSource[streamNumber] = 0;
6463                         /* Set changed flag? */
6464                     }
6465                 }
6466                 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) */
6467                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6468                         TRACE("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
6469                         This->stateBlock->streamSource[streamNumber] = 0;
6470                     }
6471                 }
6472 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6473                  else { /* This shouldn't happen */
6474                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6475                 }
6476 #endif
6477
6478             }
6479         }
6480         break;
6481         case D3DRTYPE_INDEXBUFFER:
6482         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6483         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6484             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6485                 This->updateStateBlock->pIndexData =  NULL;
6486             }
6487         }
6488         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6489             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6490                 This->stateBlock->pIndexData =  NULL;
6491             }
6492         }
6493
6494         break;
6495         default:
6496         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6497         break;
6498     }
6499
6500
6501     /* Remove the resoruce from the resourceStore */
6502     IWineD3DDeviceImpl_RemoveResource(iface, resource);
6503
6504     TRACE("Resource released\n");
6505
6506 }
6507
6508
6509 /** This function is to be called by the swapchain when it is released and it's ref = 0
6510  *****************************************************/
6511 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
6512     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6513     SwapChainList **nextSwapchain;
6514     nextSwapchain = &This->swapchains;
6515
6516     /* Check to see if the swapchian is being used as the render target */
6517     if (This->renderTarget != NULL) {
6518         IWineD3DSurface *swapchainBackBuffer;
6519
6520         IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
6521         if (This->renderTarget == swapchainBackBuffer) {
6522             /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
6523             FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6524         }
6525     }
6526
6527     /* Go through the swapchain list and try to find the swapchain being released */
6528     while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6529         nextSwapchain = &(*nextSwapchain)->next;
6530     }
6531
6532     /* Check to see if we found the swapchain */
6533     if (NULL != *nextSwapchain) {
6534         /* We found the swapchain so remove it from the list */
6535         TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6536         HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6537         *nextSwapchain = (*nextSwapchain)->next;
6538     } else {
6539         /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6540         FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6541     }
6542
6543     TRACE("swapchain (%p) released\n", swapChain);
6544     return;
6545 }
6546
6547 /**********************************************************
6548  * IWineD3DDevice VTbl follows
6549  **********************************************************/
6550
6551 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6552 {
6553     /*** IUnknown methods ***/
6554     IWineD3DDeviceImpl_QueryInterface,
6555     IWineD3DDeviceImpl_AddRef,
6556     IWineD3DDeviceImpl_Release,
6557     /*** IWineD3DDevice methods ***/
6558     IWineD3DDeviceImpl_GetParent,
6559     /*** Creation methods**/
6560     IWineD3DDeviceImpl_CreateVertexBuffer,
6561     IWineD3DDeviceImpl_CreateIndexBuffer,
6562     IWineD3DDeviceImpl_CreateStateBlock,
6563     IWineD3DDeviceImpl_CreateSurface,
6564     IWineD3DDeviceImpl_CreateTexture,
6565     IWineD3DDeviceImpl_CreateVolumeTexture,
6566     IWineD3DDeviceImpl_CreateVolume,
6567     IWineD3DDeviceImpl_CreateCubeTexture,
6568     IWineD3DDeviceImpl_CreateQuery,
6569     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6570     IWineD3DDeviceImpl_CreateVertexDeclaration,
6571     IWineD3DDeviceImpl_CreateVertexShader,
6572     IWineD3DDeviceImpl_CreatePixelShader,
6573     /*** Odd functions **/
6574     IWineD3DDeviceImpl_EvictManagedResources,
6575     IWineD3DDeviceImpl_GetAvailableTextureMem,
6576     IWineD3DDeviceImpl_GetBackBuffer,
6577     IWineD3DDeviceImpl_GetCreationParameters,
6578     IWineD3DDeviceImpl_GetDeviceCaps,
6579     IWineD3DDeviceImpl_GetDirect3D,
6580     IWineD3DDeviceImpl_GetDisplayMode,
6581     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6582     IWineD3DDeviceImpl_GetRasterStatus,
6583     IWineD3DDeviceImpl_GetSwapChain,
6584     IWineD3DDeviceImpl_Reset,
6585     IWineD3DDeviceImpl_SetDialogBoxMode,
6586     IWineD3DDeviceImpl_SetCursorProperties,
6587     IWineD3DDeviceImpl_SetCursorPosition,
6588     IWineD3DDeviceImpl_ShowCursor,
6589     IWineD3DDeviceImpl_TestCooperativeLevel,
6590     /*** Getters and setters **/
6591     IWineD3DDeviceImpl_SetClipPlane,
6592     IWineD3DDeviceImpl_GetClipPlane,
6593     IWineD3DDeviceImpl_SetClipStatus,
6594     IWineD3DDeviceImpl_GetClipStatus,
6595     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6596     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6597     IWineD3DDeviceImpl_SetDepthStencilSurface,
6598     IWineD3DDeviceImpl_GetDepthStencilSurface,
6599     IWineD3DDeviceImpl_SetFVF,
6600     IWineD3DDeviceImpl_GetFVF,
6601     IWineD3DDeviceImpl_SetGammaRamp,
6602     IWineD3DDeviceImpl_GetGammaRamp,
6603     IWineD3DDeviceImpl_SetIndices,
6604     IWineD3DDeviceImpl_GetIndices,
6605     IWineD3DDeviceImpl_SetLight,
6606     IWineD3DDeviceImpl_GetLight,
6607     IWineD3DDeviceImpl_SetLightEnable,
6608     IWineD3DDeviceImpl_GetLightEnable,
6609     IWineD3DDeviceImpl_SetMaterial,
6610     IWineD3DDeviceImpl_GetMaterial,
6611     IWineD3DDeviceImpl_SetNPatchMode,
6612     IWineD3DDeviceImpl_GetNPatchMode,
6613     IWineD3DDeviceImpl_SetPaletteEntries,
6614     IWineD3DDeviceImpl_GetPaletteEntries,
6615     IWineD3DDeviceImpl_SetPixelShader,
6616     IWineD3DDeviceImpl_GetPixelShader,
6617     IWineD3DDeviceImpl_SetPixelShaderConstant,
6618     IWineD3DDeviceImpl_GetPixelShaderConstant,
6619     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6620     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6621     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6622     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6623     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6624     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6625     IWineD3DDeviceImpl_SetPixelShaderConstantN,
6626     IWineD3DDeviceImpl_SetRenderState,
6627     IWineD3DDeviceImpl_GetRenderState,
6628     IWineD3DDeviceImpl_SetRenderTarget,
6629     IWineD3DDeviceImpl_GetRenderTarget,
6630     IWineD3DDeviceImpl_SetSamplerState,
6631     IWineD3DDeviceImpl_GetSamplerState,
6632     IWineD3DDeviceImpl_SetScissorRect,
6633     IWineD3DDeviceImpl_GetScissorRect,
6634     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6635     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6636     IWineD3DDeviceImpl_SetStreamSource,
6637     IWineD3DDeviceImpl_GetStreamSource,
6638     IWineD3DDeviceImpl_SetStreamSourceFreq,
6639     IWineD3DDeviceImpl_GetStreamSourceFreq,
6640     IWineD3DDeviceImpl_SetTexture,
6641     IWineD3DDeviceImpl_GetTexture,
6642     IWineD3DDeviceImpl_SetTextureStageState,
6643     IWineD3DDeviceImpl_GetTextureStageState,
6644     IWineD3DDeviceImpl_SetTransform,
6645     IWineD3DDeviceImpl_GetTransform,
6646     IWineD3DDeviceImpl_SetVertexDeclaration,
6647     IWineD3DDeviceImpl_GetVertexDeclaration,
6648     IWineD3DDeviceImpl_SetVertexShader,
6649     IWineD3DDeviceImpl_GetVertexShader,
6650     IWineD3DDeviceImpl_SetVertexShaderConstant,
6651     IWineD3DDeviceImpl_GetVertexShaderConstant,
6652     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6653     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6654     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6655     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6656     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6657     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6658     IWineD3DDeviceImpl_SetVertexShaderConstantN,
6659     IWineD3DDeviceImpl_SetViewport,
6660     IWineD3DDeviceImpl_GetViewport,
6661     IWineD3DDeviceImpl_MultiplyTransform,
6662     IWineD3DDeviceImpl_ValidateDevice,
6663     IWineD3DDeviceImpl_ProcessVertices,
6664     /*** State block ***/
6665     IWineD3DDeviceImpl_BeginStateBlock,
6666     IWineD3DDeviceImpl_EndStateBlock,
6667     /*** Scene management ***/
6668     IWineD3DDeviceImpl_BeginScene,
6669     IWineD3DDeviceImpl_EndScene,
6670     IWineD3DDeviceImpl_Present,
6671     IWineD3DDeviceImpl_Clear,
6672     /*** Drawing ***/
6673     IWineD3DDeviceImpl_DrawPrimitive,
6674     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6675     IWineD3DDeviceImpl_DrawPrimitiveUP,
6676     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6677     IWineD3DDeviceImpl_DrawRectPatch,
6678     IWineD3DDeviceImpl_DrawTriPatch,
6679     IWineD3DDeviceImpl_DeletePatch,
6680     IWineD3DDeviceImpl_ColorFill,
6681     IWineD3DDeviceImpl_UpdateTexture,
6682     IWineD3DDeviceImpl_UpdateSurface,
6683     IWineD3DDeviceImpl_CopyRects,
6684     IWineD3DDeviceImpl_StretchRect,
6685     IWineD3DDeviceImpl_GetRenderTargetData,
6686     IWineD3DDeviceImpl_GetFrontBufferData,
6687     /*** Internal use IWineD3DDevice methods ***/
6688     IWineD3DDeviceImpl_SetupTextureStates,
6689     /*** object tracking ***/
6690     IWineD3DDeviceImpl_SwapChainReleased,
6691     IWineD3DDeviceImpl_ResourceReleased
6692 };
6693
6694
6695 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6696     WINED3DRS_ALPHABLENDENABLE   ,
6697     WINED3DRS_ALPHAFUNC          ,
6698     WINED3DRS_ALPHAREF           ,
6699     WINED3DRS_ALPHATESTENABLE    ,
6700     WINED3DRS_BLENDOP            ,
6701     WINED3DRS_COLORWRITEENABLE   ,
6702     WINED3DRS_DESTBLEND          ,
6703     WINED3DRS_DITHERENABLE       ,
6704     WINED3DRS_FILLMODE           ,
6705     WINED3DRS_FOGDENSITY         ,
6706     WINED3DRS_FOGEND             ,
6707     WINED3DRS_FOGSTART           ,
6708     WINED3DRS_LASTPIXEL          ,
6709     WINED3DRS_SHADEMODE          ,
6710     WINED3DRS_SRCBLEND           ,
6711     WINED3DRS_STENCILENABLE      ,
6712     WINED3DRS_STENCILFAIL        ,
6713     WINED3DRS_STENCILFUNC        ,
6714     WINED3DRS_STENCILMASK        ,
6715     WINED3DRS_STENCILPASS        ,
6716     WINED3DRS_STENCILREF         ,
6717     WINED3DRS_STENCILWRITEMASK   ,
6718     WINED3DRS_STENCILZFAIL       ,
6719     WINED3DRS_TEXTUREFACTOR      ,
6720     WINED3DRS_WRAP0              ,
6721     WINED3DRS_WRAP1              ,
6722     WINED3DRS_WRAP2              ,
6723     WINED3DRS_WRAP3              ,
6724     WINED3DRS_WRAP4              ,
6725     WINED3DRS_WRAP5              ,
6726     WINED3DRS_WRAP6              ,
6727     WINED3DRS_WRAP7              ,
6728     WINED3DRS_ZENABLE            ,
6729     WINED3DRS_ZFUNC              ,
6730     WINED3DRS_ZWRITEENABLE
6731 };
6732
6733 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6734     WINED3DTSS_ADDRESSW              ,
6735     WINED3DTSS_ALPHAARG0             ,
6736     WINED3DTSS_ALPHAARG1             ,
6737     WINED3DTSS_ALPHAARG2             ,
6738     WINED3DTSS_ALPHAOP               ,
6739     WINED3DTSS_BUMPENVLOFFSET        ,
6740     WINED3DTSS_BUMPENVLSCALE         ,
6741     WINED3DTSS_BUMPENVMAT00          ,
6742     WINED3DTSS_BUMPENVMAT01          ,
6743     WINED3DTSS_BUMPENVMAT10          ,
6744     WINED3DTSS_BUMPENVMAT11          ,
6745     WINED3DTSS_COLORARG0             ,
6746     WINED3DTSS_COLORARG1             ,
6747     WINED3DTSS_COLORARG2             ,
6748     WINED3DTSS_COLOROP               ,
6749     WINED3DTSS_RESULTARG             ,
6750     WINED3DTSS_TEXCOORDINDEX         ,
6751     WINED3DTSS_TEXTURETRANSFORMFLAGS
6752 };
6753
6754 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6755     WINED3DSAMP_ADDRESSU         ,
6756     WINED3DSAMP_ADDRESSV         ,
6757     WINED3DSAMP_ADDRESSW         ,
6758     WINED3DSAMP_BORDERCOLOR      ,
6759     WINED3DSAMP_MAGFILTER        ,
6760     WINED3DSAMP_MINFILTER        ,
6761     WINED3DSAMP_MIPFILTER        ,
6762     WINED3DSAMP_MIPMAPLODBIAS    ,
6763     WINED3DSAMP_MAXMIPLEVEL      ,
6764     WINED3DSAMP_MAXANISOTROPY    ,
6765     WINED3DSAMP_SRGBTEXTURE      ,
6766     WINED3DSAMP_ELEMENTINDEX
6767 };
6768
6769 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6770     WINED3DRS_AMBIENT                       ,
6771     WINED3DRS_AMBIENTMATERIALSOURCE         ,
6772     WINED3DRS_CLIPPING                      ,
6773     WINED3DRS_CLIPPLANEENABLE               ,
6774     WINED3DRS_COLORVERTEX                   ,
6775     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
6776     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
6777     WINED3DRS_FOGDENSITY                    ,
6778     WINED3DRS_FOGEND                        ,
6779     WINED3DRS_FOGSTART                      ,
6780     WINED3DRS_FOGTABLEMODE                  ,
6781     WINED3DRS_FOGVERTEXMODE                 ,
6782     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
6783     WINED3DRS_LIGHTING                      ,
6784     WINED3DRS_LOCALVIEWER                   ,
6785     WINED3DRS_MULTISAMPLEANTIALIAS          ,
6786     WINED3DRS_MULTISAMPLEMASK               ,
6787     WINED3DRS_NORMALIZENORMALS              ,
6788     WINED3DRS_PATCHEDGESTYLE                ,
6789     WINED3DRS_POINTSCALE_A                  ,
6790     WINED3DRS_POINTSCALE_B                  ,
6791     WINED3DRS_POINTSCALE_C                  ,
6792     WINED3DRS_POINTSCALEENABLE              ,
6793     WINED3DRS_POINTSIZE                     ,
6794     WINED3DRS_POINTSIZE_MAX                 ,
6795     WINED3DRS_POINTSIZE_MIN                 ,
6796     WINED3DRS_POINTSPRITEENABLE             ,
6797     WINED3DRS_RANGEFOGENABLE                ,
6798     WINED3DRS_SPECULARMATERIALSOURCE        ,
6799     WINED3DRS_TWEENFACTOR                   ,
6800     WINED3DRS_VERTEXBLEND
6801 };
6802
6803 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6804     WINED3DTSS_TEXCOORDINDEX         ,
6805     WINED3DTSS_TEXTURETRANSFORMFLAGS
6806 };
6807
6808 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6809     WINED3DSAMP_DMAPOFFSET
6810 };