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