wined3d: Move WINED3DRS_BLENDOP to the state table.
[wine] / dlls / wined3d / device.c
1 /*
2  * IWineD3DDevice implementation
3  *
4  * Copyright 2002 Lionel Ulmer
5  * Copyright 2002-2005 Jason Edmeades
6  * Copyright 2003-2004 Raphael Junqueira
7  * Copyright 2004 Christian Costa
8  * Copyright 2005 Oliver Stieber
9  * Copyright 2006 Stefan Dösinger for CodeWeavers
10  * Copyright 2006 Henri Verbeet
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include <stdio.h>
29 #ifdef HAVE_FLOAT_H
30 # include <float.h>
31 #endif
32 #include "wined3d_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
37
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light = {
40
41     WINED3DLIGHT_DIRECTIONAL, /* Type */
42     { 1.0, 1.0, 1.0, 0.0 },   /* Diffuse r,g,b,a */
43     { 0.0, 0.0, 0.0, 0.0 },   /* Specular r,g,b,a */
44     { 0.0, 0.0, 0.0, 0.0 },   /* Ambient r,g,b,a, */
45     { 0.0, 0.0, 0.0 },        /* Position x,y,z */
46     { 0.0, 0.0, 1.0 },        /* Direction x,y,z */
47     0.0,                      /* Range */
48     0.0,                      /* Falloff */
49     0.0, 0.0, 0.0,            /* Attenuation 0,1,2 */
50     0.0,                      /* Theta */
51     0.0                       /* Phi */
52 };
53
54 /* x11drv GDI escapes */
55 #define X11DRV_ESCAPE 6789
56 enum x11drv_escape_codes
57 {
58     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
59     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
60     X11DRV_GET_FONT,      /* get current X font for a DC */
61 };
62
63 /* retrieve the X display to use on a given DC */
64 inline static Display *get_display( HDC hdc )
65 {
66     Display *display;
67     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
68
69     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
70                     sizeof(display), (LPSTR)&display )) display = NULL;
71     return display;
72 }
73
74 /* allocate one pbuffer per surface */
75 BOOL pbuffer_per_surface = FALSE;
76
77 /* static function declarations */
78 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
79
80 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
81
82 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil);
83
84 /* helper macros */
85 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
86
87 #define D3DCREATEOBJECTINSTANCE(object, type) { \
88     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
89     D3DMEMCHECK(object, pp##type); \
90     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
91     object->wineD3DDevice = This; \
92     object->parent       = parent; \
93     object->ref          = 1; \
94     *pp##type = (IWineD3D##type *) object; \
95 }
96
97 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
98     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
99     D3DMEMCHECK(object, pp##type); \
100     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
101     object->parent       = parent; \
102     object->ref          = 1; \
103     object->baseShader.device = (IWineD3DDevice*) This; \
104     *pp##type = (IWineD3D##type *) object; \
105 }
106
107 #define  D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
108     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
109     D3DMEMCHECK(object, pp##type); \
110     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
111     object->resource.wineD3DDevice   = This; \
112     object->resource.parent          = parent; \
113     object->resource.resourceType    = d3dtype; \
114     object->resource.ref             = 1; \
115     object->resource.pool            = Pool; \
116     object->resource.format          = Format; \
117     object->resource.usage           = Usage; \
118     object->resource.size            = _size; \
119     /* Check that we have enough video ram left */ \
120     if (Pool == WINED3DPOOL_DEFAULT) { \
121         if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
122             WARN("Out of 'bogus' video memory\n"); \
123             HeapFree(GetProcessHeap(), 0, object); \
124             *pp##type = NULL; \
125             return WINED3DERR_OUTOFVIDEOMEMORY; \
126         } \
127         globalChangeGlRam(_size); \
128     } \
129     object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
130     if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
131         FIXME("Out of memory!\n"); \
132         HeapFree(GetProcessHeap(), 0, object); \
133         *pp##type = NULL; \
134         return WINED3DERR_OUTOFVIDEOMEMORY; \
135     } \
136     *pp##type = (IWineD3D##type *) object; \
137     IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
138     TRACE("(%p) : Created resource %p\n", This, object); \
139 }
140
141 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
142     _basetexture.levels     = Levels; \
143     _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
144     _basetexture.LOD        = 0; \
145     _basetexture.dirty      = TRUE; \
146 }
147
148 /**********************************************************
149  * Global variable / Constants follow
150  **********************************************************/
151 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
152
153 /**********************************************************
154  * Utility functions follow
155  **********************************************************/
156 /* Convert the WINED3DLIGHT properties into equivalent gl lights */
157 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
158
159     float quad_att;
160     float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
161     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
162
163     /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
164     glMatrixMode(GL_MODELVIEW);
165     glPushMatrix();
166     glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
167
168     /* Diffuse: */
169     colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
170     colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
171     colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
172     colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
173     glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
174     checkGLcall("glLightfv");
175
176     /* Specular */
177     colRGBA[0] = lightInfo->OriginalParms.Specular.r;
178     colRGBA[1] = lightInfo->OriginalParms.Specular.g;
179     colRGBA[2] = lightInfo->OriginalParms.Specular.b;
180     colRGBA[3] = lightInfo->OriginalParms.Specular.a;
181     glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
182     checkGLcall("glLightfv");
183
184     /* Ambient */
185     colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
186     colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
187     colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
188     colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
189     glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
190     checkGLcall("glLightfv");
191
192     /* Attenuation - Are these right? guessing... */
193     glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
194     checkGLcall("glLightf");
195     glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
196     checkGLcall("glLightf");
197
198     if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
199         quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
200     } else {
201         quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
202     }
203
204     if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
205     glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
206     checkGLcall("glLightf");
207
208     switch (lightInfo->OriginalParms.Type) {
209     case WINED3DLIGHT_POINT:
210         /* Position */
211         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
212         checkGLcall("glLightfv");
213         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
214         checkGLcall("glLightf");
215         /* FIXME: Range */
216         break;
217
218     case WINED3DLIGHT_SPOT:
219         /* Position */
220         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
221         checkGLcall("glLightfv");
222         /* Direction */
223         glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
224         checkGLcall("glLightfv");
225         glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
226         checkGLcall("glLightf");
227         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
228         checkGLcall("glLightf");
229         /* FIXME: Range */
230         break;
231
232     case WINED3DLIGHT_DIRECTIONAL:
233         /* Direction */
234         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
235         checkGLcall("glLightfv");
236         glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
237         checkGLcall("glLightf");
238         glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
239         checkGLcall("glLightf");
240         break;
241
242     default:
243         FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
244     }
245
246     /* Restore the modelview matrix */
247     glPopMatrix();
248 }
249
250 /**********************************************************
251  * GLSL helper functions follow
252  **********************************************************/
253
254 /** Attach a GLSL pixel or vertex shader object to the shader program */
255 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
256
257     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
258     GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
259     if (This->stateBlock->glsl_program && shaderObj != 0) {
260         TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
261         GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
262         checkGLcall("glAttachObjectARB");
263     }
264 }
265
266 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
267  * It sets the programId on the current StateBlock (because it should be called
268  * inside of the DrawPrimitive() part of the render loop).
269  *
270  * If a program for the given combination does not exist, create one, and store
271  * the program in the list.  If it creates a program, it will link the given 
272  * objects, too.
273  * 
274  * We keep the shader programs around on a list because linking
275  * shader objects together is an expensive operation.  It's much
276  * faster to loop through a list of pre-compiled & linked programs
277  * each time that the application sets a new pixel or vertex shader
278  * than it is to re-link them together at that time.
279  *
280  * The list will be deleted in IWineD3DDevice::Release().
281  */
282 void set_glsl_shader_program(IWineD3DDevice *iface) {
283
284     IWineD3DDeviceImpl *This               = (IWineD3DDeviceImpl *)iface;
285     IWineD3DPixelShader  *pshader          = This->stateBlock->pixelShader;
286     IWineD3DVertexShader *vshader          = This->stateBlock->vertexShader;
287     struct glsl_shader_prog_link *curLink  = NULL;
288     struct glsl_shader_prog_link *newLink  = NULL;
289     struct list *ptr                       = NULL;
290     GLhandleARB programId                  = 0;
291     int i;
292     char glsl_name[8];
293     
294     ptr = list_head( &This->glsl_shader_progs );
295     while (ptr) {
296         /* At least one program exists - see if it matches our ps/vs combination */
297         curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
298         if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
299             /* Existing Program found, use it */
300             TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n", 
301                    curLink->programId);
302             This->stateBlock->glsl_program = curLink;
303             return;
304         }
305         /* This isn't the entry we need - try the next one */
306         ptr = list_next( &This->glsl_shader_progs, ptr );
307     }
308
309     /* If we get to this point, then no matching program exists, so we create one */
310     programId = GL_EXTCALL(glCreateProgramObjectARB());
311     TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
312
313     /* Allocate a new link for the list of programs */
314     newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
315     newLink->programId    = programId;
316     This->stateBlock->glsl_program = newLink;
317    
318     /* Attach GLSL vshader */ 
319     if (NULL != vshader && This->vs_selected_mode == SHADER_GLSL) {
320         int i;
321         int max_attribs = 16;   /* TODO: Will this always be the case? It is at the moment... */
322         char tmp_name[10];
323     
324         TRACE("Attaching vertex shader to GLSL program\n");    
325         attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
326         
327         /* Bind vertex attributes to a corresponding index number to match
328          * the same index numbers as ARB_vertex_programs (makes loading
329          * vertex attributes simpler).  With this method, we can use the
330          * exact same code to load the attributes later for both ARB and 
331          * GLSL shaders.
332          * 
333          * We have to do this here because we need to know the Program ID
334          * in order to make the bindings work, and it has to be done prior
335          * to linking the GLSL program. */
336         for (i = 0; i < max_attribs; ++i) {
337              snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
338              GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
339         }
340         checkGLcall("glBindAttribLocationARB");
341         newLink->vertexShader = vshader;
342     }
343     
344     /* Attach GLSL pshader */
345     if (NULL != pshader && This->ps_selected_mode == SHADER_GLSL) {
346         TRACE("Attaching pixel shader to GLSL program\n");
347         attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
348         newLink->pixelShader = pshader;
349     }    
350
351     /* Link the program */
352     TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
353     GL_EXTCALL(glLinkProgramARB(programId));
354     print_glsl_info_log(&GLINFO_LOCATION, programId);
355     list_add_head( &This->glsl_shader_progs, &newLink->entry);
356
357     newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF));
358     for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
359         snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i);
360         newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
361     }
362     newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF));
363     for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
364         snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i);
365         newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
366     }
367
368     return;
369 }
370
371 /** Detach the GLSL pixel or vertex shader object from the shader program */
372 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
373
374     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
375
376     if (shaderObj != 0 && programId != 0) {
377         TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
378         GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
379         checkGLcall("glDetachObjectARB");
380     }
381 }
382
383 /** Delete a GLSL shader program */
384 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
385
386     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
387     
388     if (obj != 0) {
389         TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
390         GL_EXTCALL(glDeleteObjectARB(obj));
391         checkGLcall("glDeleteObjectARB");
392     }
393 }
394
395 /** Delete the list of linked programs this shader is associated with.
396  * Also at this point, check to see if there are any objects left attached
397  * to each GLSL program.  If not, delete the GLSL program object.
398  * This will be run when a device is released. */
399 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
400     
401     struct list *ptr                       = NULL;
402     struct glsl_shader_prog_link *curLink  = NULL;
403     IWineD3DDeviceImpl *This               = (IWineD3DDeviceImpl *)iface;
404     
405     int numAttached = 0;
406     int i;
407     GLhandleARB objList[2];   /* There should never be more than 2 objects attached 
408                                  (one pixel shader and one vertex shader at most) */
409     
410     ptr = list_head( &This->glsl_shader_progs );
411     while (ptr) {
412         /* First, get the current item,
413          * save the link to the next pointer, 
414          * detach and delete shader objects,
415          * then de-allocate the list item's memory */
416         curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
417         ptr = list_next( &This->glsl_shader_progs, ptr );
418
419         /* See if this object is still attached to the program - it may have been detached already */
420         GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
421         TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
422         for (i = 0; i < numAttached; i++) {
423             detach_glsl_shader(iface, objList[i], curLink->programId);
424         }
425         
426         delete_glsl_shader_program(iface, curLink->programId);
427
428         /* Free the uniform locations */
429         HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
430         HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
431
432         /* Free the memory for this list item */    
433         HeapFree(GetProcessHeap(), 0, curLink);
434     }
435 }
436
437
438 /* Apply the current values to the specified texture stage */
439 static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
440     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
441     float col[4];
442
443     union {
444         float f;
445         DWORD d;
446     } tmpvalue;
447
448     /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
449     clamping, MIPLOD, etc. This will work for up to 16 samplers.
450     */
451    
452     if (Sampler >= GL_LIMITS(sampler_stages)) {
453         FIXME("Trying to set the state of more samplers %d than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
454         return;
455     }
456     VTRACE(("Activating appropriate texture state %d\n", Sampler));
457     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
458         ENTER_GL();
459         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
460         checkGLcall("glActiveTextureARB");
461         LEAVE_GL();
462         /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
463     } else if (Sampler > 0) {
464         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
465         return;
466     }
467
468     /* TODO: change this to a lookup table
469         LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
470         LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
471         etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
472         especially when there are a number of groups of states. */
473
474     TRACE("-----------------------> Updating the texture at Sampler %d to have new texture state information\n", Sampler);
475
476     /* 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  */
477 #define APPLY_STATE(_state)     IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
478 /* these are the only two supported states that need to be applied */
479     APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
480     APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
481 #if 0 /* not supported at the moment */
482     APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
483     APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
484     APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
485     APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
486     APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
487     APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
488     APPLY_STATE(WINED3DTSS_RESULTARG);
489     APPLY_STATE(WINED3DTSS_CONSTANT);
490 #endif
491     /* a quick sanity check in case someone forgot to update this function */
492     if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
493         FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
494     }
495 #undef APPLY_STATE
496
497     /* apply any sampler states that always need applying */
498     if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
499         tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
500         glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
501                 GL_TEXTURE_LOD_BIAS_EXT,
502                 tmpvalue.f);
503         checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
504     }
505
506     D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
507     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
508     checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
509
510     /* TODO: NV_POINT_SPRITE */
511     if (GL_SUPPORT(ARB_POINT_SPRITE)) {
512         if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
513            /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
514            glDisable(GL_POINT_SMOOTH);
515
516            /* Centre the texture on the vertex */
517            VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
518            glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
519
520            VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
521            glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
522            checkGLcall("glTexEnvf(...)");
523            VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
524            glEnable( GL_POINT_SPRITE_ARB );
525            checkGLcall("glEnable(...)");
526         } else {
527            VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
528            glDisable( GL_POINT_SPRITE_ARB );
529            checkGLcall("glEnable(...)");
530         }
531     }
532
533     TRACE("-----------------------> Updated the texture at Sampler %d to have new texture state information\n", Sampler);
534 }
535
536 /**********************************************************
537  * IUnknown parts follows
538  **********************************************************/
539
540 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
541 {
542     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
543
544     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
545     if (IsEqualGUID(riid, &IID_IUnknown)
546         || IsEqualGUID(riid, &IID_IWineD3DBase)
547         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
548         IUnknown_AddRef(iface);
549         *ppobj = This;
550         return S_OK;
551     }
552     *ppobj = NULL;
553     return E_NOINTERFACE;
554 }
555
556 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
557     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
558     ULONG refCount = InterlockedIncrement(&This->ref);
559
560     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
561     return refCount;
562 }
563
564 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
565     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
566     ULONG refCount = InterlockedDecrement(&This->ref);
567
568     TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
569
570     if (!refCount) {
571         if (This->fbo) {
572             GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
573         }
574
575         /* TODO: Clean up all the surfaces and textures! */
576         /* NOTE: You must release the parent if the object was created via a callback
577         ** ***************************/
578
579         /* Delete any GLSL shader programs that may exist */
580         if (This->vs_selected_mode == SHADER_GLSL ||
581             This->ps_selected_mode == SHADER_GLSL)
582             delete_glsl_shader_list(iface);
583     
584         /* Release the update stateblock */
585         if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
586             if(This->updateStateBlock != This->stateBlock)
587                 FIXME("(%p) Something's still holding the Update stateblock\n",This);
588         }
589         This->updateStateBlock = NULL;
590         { /* because were not doing proper internal refcounts releasing the primary state block
591             causes recursion with the extra checks in ResourceReleased, to avoid this we have
592             to set this->stateBlock = NULL; first */
593             IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
594             This->stateBlock = NULL;
595
596             /* Release the stateblock */
597             if(IWineD3DStateBlock_Release(stateBlock) > 0){
598                     FIXME("(%p) Something's still holding the Update stateblock\n",This);
599             }
600         }
601
602         if (This->resources != NULL ) {
603             FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
604             dumpResources(This->resources);
605         }
606
607
608         IWineD3D_Release(This->wineD3D);
609         This->wineD3D = NULL;
610         HeapFree(GetProcessHeap(), 0, This);
611         TRACE("Freed device  %p\n", This);
612         This = NULL;
613     }
614     return refCount;
615 }
616
617 /**********************************************************
618  * IWineD3DDevice implementation follows
619  **********************************************************/
620 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
621     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
622     *pParent = This->parent;
623     IUnknown_AddRef(This->parent);
624     return WINED3D_OK;
625 }
626
627 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
628     IWineD3DDeviceImpl *This = object->resource.wineD3DDevice;  /* Needed for GL_EXTCALL */
629     GLenum error, glUsage;
630     DWORD vboUsage = object->resource.usage;
631     if(object->Flags & VBFLAG_VBOCREATEFAIL) {
632         WARN("Creating a vbo failed once, not trying again\n");
633         return;
634     }
635
636     TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p  Usage(%s)\n", object, debug_d3dusage(vboUsage));
637
638     ENTER_GL();
639     /* Make sure that the gl error is cleared. Do not use checkGLcall
640       * here because checkGLcall just prints a fixme and continues. However,
641       * if an error during VBO creation occurs we can fall back to non-vbo operation
642       * with full functionality(but performance loss)
643       */
644     while(glGetError() != GL_NO_ERROR);
645
646     /* Basically the FVF parameter passed to CreateVertexBuffer is no good
647       * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
648       * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
649       * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
650       * to check if the rhw and color values are in the correct format.
651       */
652
653     GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
654     error = glGetError();
655     if(object->vbo == 0 || error != GL_NO_ERROR) {
656         WARN("Failed to create a VBO with error %d\n", error);
657         goto error;
658     }
659
660     GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
661     error = glGetError();
662     if(error != GL_NO_ERROR) {
663         WARN("Failed to bind the VBO, error %d\n", error);
664         goto error;
665     }
666
667     /* Transformed vertices are horribly inflexible. If the app specifies an
668       * vertex buffer with transformed vertices in default pool without DYNAMIC
669       * usage assume DYNAMIC usage and print a warning. The app will have to update
670       * the vertices regularily for them to be useful
671       */
672     if(((object->fvf & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) &&
673         !(vboUsage & WINED3DUSAGE_DYNAMIC)) {
674         WARN("Application creates a vertex buffer holding transformed vertices which doesn't specify dynamic usage\n");
675         vboUsage |= WINED3DUSAGE_DYNAMIC;
676     }
677
678     /* Don't use static, because dx apps tend to update the buffer
679       * quite often even if they specify 0 usage
680       */
681     switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
682         case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
683             TRACE("Gl usage = GL_STREAM_DRAW\n");
684             glUsage = GL_STREAM_DRAW_ARB;
685             break;
686         case D3DUSAGE_WRITEONLY:
687             TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
688             glUsage = GL_DYNAMIC_DRAW_ARB;
689             break;
690         case D3DUSAGE_DYNAMIC:
691             TRACE("Gl usage = GL_STREAM_COPY\n");
692             glUsage = GL_STREAM_COPY_ARB;
693             break;
694         default:
695             TRACE("Gl usage = GL_DYNAMIC_COPY\n");
696             glUsage = GL_DYNAMIC_COPY_ARB;
697             break;
698     }
699
700     /* Reserve memory for the buffer. The amount of data won't change
701       * so we are safe with calling glBufferData once with a NULL ptr and
702       * calling glBufferSubData on updates
703       */
704     GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
705     error = glGetError();
706     if(error != GL_NO_ERROR) {
707         WARN("glBufferDataARB failed with error %d\n", error);
708         goto error;
709     }
710
711     LEAVE_GL();
712
713     return;
714     error:
715     /* Clean up all vbo init, but continue because we can work without a vbo :-) */
716     FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
717     if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
718     object->vbo = 0;
719     object->Flags |= VBFLAG_VBOCREATEFAIL;
720     LEAVE_GL();
721     return;
722 }
723
724 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, 
725                              DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
726                              IUnknown *parent) {
727     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
728     IWineD3DVertexBufferImpl *object;
729     WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
730     int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
731     BOOL conv;
732     D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
733
734     TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
735     *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
736
737     if(Size == 0) return WINED3DERR_INVALIDCALL;
738
739     if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
740         object->resource.allocatedMemory  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
741     }
742     object->fvf = FVF;
743
744     /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
745      * drawStridedFast (half-life 2).
746      *
747      * Basically converting the vertices in the buffer is quite expensive, and observations
748      * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
749      * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
750      *
751      * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
752      * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
753      * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
754      * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
755      * dx7 apps.
756      * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
757      * more. In this call we can convert dx7 buffers too.
758      */
759     conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
760     if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && 
761         (dxVersion > 7 || !conv) ) {
762         CreateVBO(object);
763
764         /* DX7 buffers can be locked directly into the VBO (no conversion, see above */
765         if(dxVersion == 7 && object->vbo) {
766             HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
767             object->resource.allocatedMemory = NULL;
768         }
769
770     }
771     return WINED3D_OK;
772 }
773
774 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage, 
775                                                     WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
776                                                     HANDLE *sharedHandle, IUnknown *parent) {
777     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
778     IWineD3DIndexBufferImpl *object;
779     TRACE("(%p) Creating index buffer\n", This);
780     
781     /* Allocate the storage for the device */
782     D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
783     
784     /*TODO: use VBO's */
785     if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
786         object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
787     }
788
789     TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format, 
790                            debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
791     *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
792
793     return WINED3D_OK;
794 }
795
796 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
797
798     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
799     IWineD3DStateBlockImpl *object;
800     int i, j;
801     HRESULT temp_result;
802
803     D3DCREATEOBJECTINSTANCE(object, StateBlock)
804     object->blockType     = Type;
805
806     /* Special case - Used during initialization to produce a placeholder stateblock
807           so other functions called can update a state block                         */
808     if (Type == WINED3DSBT_INIT) {
809         /* Don't bother increasing the reference count otherwise a device will never
810            be freed due to circular dependencies                                   */
811         return WINED3D_OK;
812     }
813     
814     temp_result = allocate_shader_constants(object);
815     if (WINED3D_OK != temp_result)
816         return temp_result;
817
818     /* Otherwise, might as well set the whole state block to the appropriate values  */
819     if (This->stateBlock != NULL)
820         stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
821     else
822         memset(object->streamFreq, 1, sizeof(object->streamFreq));
823
824     /* Reset the ref and type after kludging it */
825     object->wineD3DDevice = This;
826     object->ref           = 1;
827     object->blockType     = Type;
828
829     TRACE("Updating changed flags appropriate for type %d\n", Type);
830
831     if (Type == WINED3DSBT_ALL) {
832
833         TRACE("ALL => Pretend everything has changed\n");
834         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
835     
836     } else if (Type == WINED3DSBT_PIXELSTATE) {
837
838         TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
839         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
840
841         object->changed.pixelShader = TRUE;
842
843         /* Pixel Shader Constants */
844         for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
845             object->changed.pixelShaderConstantsF[i] = TRUE;
846         for (i = 0; i < MAX_CONST_B; ++i)
847             object->changed.pixelShaderConstantsB[i] = TRUE;
848         for (i = 0; i < MAX_CONST_I; ++i)
849             object->changed.pixelShaderConstantsI[i] = TRUE;
850         
851         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
852             object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
853         }
854         for (j = 0; j < GL_LIMITS(texture_stages); j++) {
855             for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
856                 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
857             }
858         }
859         for (j = 0 ; j < 16; j++) {
860             for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
861
862                 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
863             }
864         }
865
866     } else if (Type == WINED3DSBT_VERTEXSTATE) {
867
868         TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
869         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
870
871         object->changed.vertexShader = TRUE;
872
873         /* Vertex Shader Constants */
874         for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
875             object->changed.vertexShaderConstantsF[i] = TRUE;
876         for (i = 0; i < MAX_CONST_B; ++i)
877             object->changed.vertexShaderConstantsB[i] = TRUE;
878         for (i = 0; i < MAX_CONST_I; ++i)
879             object->changed.vertexShaderConstantsI[i] = TRUE;
880  
881         for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
882             object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
883         }
884         for (j = 0; j < GL_LIMITS(texture_stages); j++) {
885             for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
886                 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
887             }
888         }
889         for (j = 0 ; j < 16; j++){
890             for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
891                 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
892             }
893         }
894
895     /* Duplicate light chain */
896     {
897         PLIGHTINFOEL *src = NULL;
898         PLIGHTINFOEL *dst = NULL;
899         PLIGHTINFOEL *newEl = NULL;
900         src = This->stateBlock->lights;
901         object->lights = NULL;
902
903
904         while (src) {
905             newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
906             if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
907             memcpy(newEl, src, sizeof(PLIGHTINFOEL));
908             newEl->prev = dst;
909             newEl->changed = TRUE;
910             newEl->enabledChanged = TRUE;
911             if (dst == NULL) {
912                 object->lights = newEl;
913             } else {
914                 dst->next = newEl;
915             }
916             dst = newEl;
917             src = src->next;
918         }
919
920      }
921
922     } else {
923         FIXME("Unrecognized state block type %d\n", Type);
924     }
925
926     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
927     return WINED3D_OK;
928 }
929
930
931 /* ************************************
932 MSDN:
933 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
934
935 Discard
936  [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. 
937
938 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.
939
940 ******************************** */
941  
942 static HRESULT  WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
943     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;    
944     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
945     unsigned int pow2Width, pow2Height;
946     unsigned int Size       = 1;
947     const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
948     TRACE("(%p) Create surface\n",This);
949     
950     /** FIXME: Check ranges on the inputs are valid 
951      * MSDN
952      *   MultisampleQuality
953      *    [in] Quality level. The valid range is between zero and one less than the level
954      *    returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. 
955      *    Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
956      *    values of paired render targets, depth stencil surfaces, and the MultiSample type
957      *    must all match.
958       *******************************/
959
960
961     /**
962     * TODO: Discard MSDN
963     * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
964     *
965     * If this flag is set, the contents of the depth stencil buffer will be
966     * invalid after calling either IDirect3DDevice9::Present or  * IDirect3DDevice9::SetDepthStencilSurface
967     * with a different depth surface.
968     *
969     *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
970     ***************************/
971
972     if(MultisampleQuality < 0) {
973         FIXME("Invalid multisample level %d\n", MultisampleQuality);
974         return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
975     }
976
977     if(MultisampleQuality > 0) {
978         FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
979         MultisampleQuality=0;
980     }
981
982     /** FIXME: Check that the format is supported
983     *    by the device.
984       *******************************/
985
986     /* Non-power2 support */
987     if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
988         pow2Width = Width;
989         pow2Height = Height;
990     } else {
991         /* Find the nearest pow2 match */
992         pow2Width = pow2Height = 1;
993         while (pow2Width < Width) pow2Width <<= 1;
994         while (pow2Height < Height) pow2Height <<= 1;
995     }
996
997     if (pow2Width > Width || pow2Height > Height) {
998          /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
999         if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
1000                || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
1001             FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
1002                     This, Width, Height);
1003             return WINED3DERR_NOTAVAILABLE;
1004         }
1005     }
1006
1007     /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
1008      *  it is based around 4x4 pixel blocks it requires padding, so allocate enough
1009      *  space!
1010       *********************************/
1011     if (WINED3DFMT_UNKNOWN == Format) {
1012         Size = 0;
1013     } else if (Format == WINED3DFMT_DXT1) {
1014         /* DXT1 is half byte per pixel */
1015        Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
1016
1017     } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
1018                Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
1019        Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
1020     } else {
1021        /* The pitch is a multiple of 4 bytes */
1022        Size = ((pow2Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1023        Size *= pow2Height;
1024     }
1025
1026     /** Create and initialise the surface resource **/
1027     D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
1028     /* "Standalone" surface */
1029     IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
1030
1031     object->currentDesc.Width      = Width;
1032     object->currentDesc.Height     = Height;
1033     object->currentDesc.MultiSampleType    = MultiSample;
1034     object->currentDesc.MultiSampleQuality = MultisampleQuality;
1035
1036     /* Setup some glformat defaults */
1037     object->glDescription.glFormat         = tableEntry->glFormat;
1038     object->glDescription.glFormatInternal = tableEntry->glInternal;
1039     object->glDescription.glType           = tableEntry->glType;
1040
1041     object->glDescription.textureName      = 0;
1042     object->glDescription.level            = Level;
1043     object->glDescription.target           = GL_TEXTURE_2D;
1044
1045     /* Internal data */
1046     object->pow2Width  = pow2Width;
1047     object->pow2Height = pow2Height;
1048
1049     /* Flags */
1050     object->Flags      = 0; /* We start without flags set */
1051     object->Flags     |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
1052     object->Flags     |= Discard ? SFLAG_DISCARD : 0;
1053     object->Flags     |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
1054     object->Flags     |= Lockable ? SFLAG_LOCKABLE : 0;
1055
1056
1057     if (WINED3DFMT_UNKNOWN != Format) {
1058         object->bytesPerPixel = tableEntry->bpp;
1059         object->pow2Size = ((pow2Width * object->bytesPerPixel) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1060         object->pow2Size *= pow2Height;
1061     } else {
1062         object->bytesPerPixel = 0;
1063         object->pow2Size      = 0;
1064     }
1065
1066     /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
1067
1068     TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
1069
1070     /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
1071     * this function is too deep to need to care about things like this.
1072     * Levels need to be checked too, and possibly Type since they all affect what can be done.
1073     * ****************************************/
1074     switch(Pool) {
1075     case WINED3DPOOL_SCRATCH:
1076         if(!Lockable)
1077             FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE \
1078                 which are mutually exclusive, setting lockable to true\n");
1079                 Lockable = TRUE;
1080     break;
1081     case WINED3DPOOL_SYSTEMMEM:
1082         if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
1083                                     this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
1084     case WINED3DPOOL_MANAGED:
1085         if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
1086                                                 Usage of DYNAMIC which are mutually exclusive, not doing \
1087                                                 anything just telling you.\n");
1088     break;
1089     case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
1090         if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
1091            && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
1092             WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
1093     break;
1094     default:
1095         FIXME("(%p) Unknown pool %d\n", This, Pool);
1096     break;
1097     };
1098
1099     if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
1100         FIXME("Trying to create a render target that isn't in the default pool\n");
1101     }
1102
1103     /* mark the texture as dirty so that it gets loaded first time around*/
1104     IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
1105     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
1106            This, Width, Height, Format, debug_d3dformat(Format),
1107            (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
1108
1109     /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
1110     if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
1111         This->ddraw_primary = (IWineD3DSurface *) object;
1112
1113     /* Look at the implementation and set the correct Vtable */
1114     switch(Impl) {
1115         case SURFACE_OPENGL:
1116             /* Nothing to do, it's set already */
1117             break;
1118
1119         case SURFACE_GDI:
1120             object->lpVtbl = &IWineGDISurface_Vtbl;
1121             break;
1122
1123         default:
1124             /* To be sure to catch this */
1125             ERR("Unknown requested surface implementation %d!\n", Impl);
1126             IWineD3DSurface_Release((IWineD3DSurface *) object);
1127             return WINED3DERR_INVALIDCALL;
1128     }
1129
1130     /* Call the private setup routine */
1131     return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
1132
1133 }
1134
1135 static HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
1136                                                  DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
1137                                                  IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
1138                                                  D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1139
1140     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1141     IWineD3DTextureImpl *object;
1142     unsigned int i;
1143     UINT tmpW;
1144     UINT tmpH;
1145     HRESULT hr;
1146     unsigned int pow2Width;
1147     unsigned int pow2Height;
1148
1149
1150     TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
1151     TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
1152             Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
1153
1154     /* TODO: It should only be possible to create textures for formats 
1155              that are reported as supported */
1156     if (WINED3DFMT_UNKNOWN >= Format) {
1157         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1158         return WINED3DERR_INVALIDCALL;
1159     }
1160
1161     D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
1162     D3DINITIALIZEBASETEXTURE(object->baseTexture);    
1163     object->width  = Width;
1164     object->height = Height;
1165
1166     /** Non-power2 support **/
1167     if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
1168         pow2Width = Width;
1169         pow2Height = Height;
1170     } else {
1171         /* Find the nearest pow2 match */
1172         pow2Width = pow2Height = 1;
1173         while (pow2Width < Width) pow2Width <<= 1;
1174         while (pow2Height < Height) pow2Height <<= 1;
1175     }
1176
1177     /** FIXME: add support for real non-power-two if it's provided by the video card **/
1178     /* Precalculated scaling for 'faked' non power of two texture coords */
1179     object->pow2scalingFactorX  =  (((float)Width)  / ((float)pow2Width));
1180     object->pow2scalingFactorY  =  (((float)Height) / ((float)pow2Height));
1181     TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
1182
1183     /* Calculate levels for mip mapping */
1184     if (Levels == 0) {
1185         TRACE("calculating levels %d\n", object->baseTexture.levels);
1186         object->baseTexture.levels++;
1187         tmpW = Width;
1188         tmpH = Height;
1189         while (tmpW > 1 || tmpH > 1) {
1190             tmpW = max(1, tmpW >> 1);
1191             tmpH = max(1, tmpH >> 1);
1192             object->baseTexture.levels++;
1193         }
1194         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1195     }
1196
1197     /* Generate all the surfaces */
1198     tmpW = Width;
1199     tmpH = Height;
1200     for (i = 0; i < object->baseTexture.levels; i++)
1201     {
1202         /* use the callback to create the texture surface */
1203         hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
1204         if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
1205             FIXME("Failed to create surface  %p\n", object);
1206             /* clean up */
1207             object->surfaces[i] = NULL;
1208             IWineD3DTexture_Release((IWineD3DTexture *)object);
1209
1210             *ppTexture = NULL;
1211             return hr;
1212         }
1213
1214         IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
1215         TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
1216         /* calculate the next mipmap level */
1217         tmpW = max(1, tmpW >> 1);
1218         tmpH = max(1, tmpH >> 1);
1219     }
1220
1221     TRACE("(%p) : Created  texture %p\n", This, object);
1222     return WINED3D_OK;
1223 }
1224
1225 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1226                                                       UINT Width, UINT Height, UINT Depth,
1227                                                       UINT Levels, DWORD Usage,
1228                                                       WINED3DFORMAT Format, WINED3DPOOL Pool,
1229                                                       IWineD3DVolumeTexture **ppVolumeTexture,
1230                                                       HANDLE *pSharedHandle, IUnknown *parent,
1231                                                       D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1232
1233     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
1234     IWineD3DVolumeTextureImpl *object;
1235     unsigned int               i;
1236     UINT                       tmpW;
1237     UINT                       tmpH;
1238     UINT                       tmpD;
1239
1240     /* TODO: It should only be possible to create textures for formats 
1241              that are reported as supported */
1242     if (WINED3DFMT_UNKNOWN >= Format) {
1243         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1244         return WINED3DERR_INVALIDCALL;
1245     }
1246
1247     D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1248     D3DINITIALIZEBASETEXTURE(object->baseTexture);
1249
1250     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1251           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1252
1253     object->width  = Width;
1254     object->height = Height;
1255     object->depth  = Depth;
1256
1257     /* Calculate levels for mip mapping */
1258     if (Levels == 0) {
1259         object->baseTexture.levels++;
1260         tmpW = Width;
1261         tmpH = Height;
1262         tmpD = Depth;
1263         while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1264             tmpW = max(1, tmpW >> 1);
1265             tmpH = max(1, tmpH >> 1);
1266             tmpD = max(1, tmpD >> 1);
1267             object->baseTexture.levels++;
1268         }
1269         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1270     }
1271
1272     /* Generate all the surfaces */
1273     tmpW = Width;
1274     tmpH = Height;
1275     tmpD = Depth;
1276
1277     for (i = 0; i < object->baseTexture.levels; i++)
1278     {
1279         /* Create the volume */
1280         D3DCB_CreateVolume(This->parent, parent, Width, Height, Depth, Format, Pool, Usage,
1281                            (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1282
1283         /* Set its container to this object */
1284         IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1285
1286         /* calcualte the next mipmap level */
1287         tmpW = max(1, tmpW >> 1);
1288         tmpH = max(1, tmpH >> 1);
1289         tmpD = max(1, tmpD >> 1);
1290     }
1291
1292     *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1293     TRACE("(%p) : Created volume texture %p\n", This, object);
1294     return WINED3D_OK;
1295 }
1296
1297 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1298                                                UINT Width, UINT Height, UINT Depth,
1299                                                DWORD Usage,
1300                                                WINED3DFORMAT Format, WINED3DPOOL Pool,
1301                                                IWineD3DVolume** ppVolume,
1302                                                HANDLE* pSharedHandle, IUnknown *parent) {
1303
1304     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
1305     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
1306     const PixelFormatDesc *formatDesc  = getFormatDescEntry(Format);
1307
1308     D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1309
1310     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1311           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1312
1313     object->currentDesc.Width   = Width;
1314     object->currentDesc.Height  = Height;
1315     object->currentDesc.Depth   = Depth;
1316     object->bytesPerPixel       = formatDesc->bpp;
1317
1318     /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1319     object->lockable            = TRUE;
1320     object->locked              = FALSE;
1321     memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1322     object->dirty               = TRUE;
1323
1324     return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1325 }
1326
1327 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1328                                                     UINT Levels, DWORD Usage,
1329                                                     WINED3DFORMAT Format, WINED3DPOOL Pool,
1330                                                     IWineD3DCubeTexture **ppCubeTexture,
1331                                                     HANDLE *pSharedHandle, IUnknown *parent,
1332                                                     D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1333
1334     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1335     IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1336     unsigned int             i, j;
1337     UINT                     tmpW;
1338     HRESULT                  hr;
1339     unsigned int pow2EdgeLength  = EdgeLength;
1340
1341     /* TODO: It should only be possible to create textures for formats 
1342              that are reported as supported */
1343     if (WINED3DFMT_UNKNOWN >= Format) {
1344         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1345         return WINED3DERR_INVALIDCALL;
1346     }
1347
1348     D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1349     D3DINITIALIZEBASETEXTURE(object->baseTexture);
1350
1351     TRACE("(%p) Create Cube Texture\n", This);
1352
1353     /** Non-power2 support **/
1354
1355     /* Find the nearest pow2 match */
1356     pow2EdgeLength = 1;
1357     while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1358
1359     object->edgeLength           = EdgeLength;
1360     /* TODO: support for native non-power 2 */
1361     /* Precalculated scaling for 'faked' non power of two texture coords */
1362     object->pow2scalingFactor    = ((float)EdgeLength) / ((float)pow2EdgeLength);
1363
1364     /* Calculate levels for mip mapping */
1365     if (Levels == 0) {
1366         object->baseTexture.levels++;
1367         tmpW = EdgeLength;
1368         while (tmpW > 1) {
1369             tmpW = max(1, tmpW >> 1);
1370             object->baseTexture.levels++;
1371         }
1372         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1373     }
1374
1375     /* Generate all the surfaces */
1376     tmpW = EdgeLength;
1377     for (i = 0; i < object->baseTexture.levels; i++) {
1378
1379         /* Create the 6 faces */
1380         for (j = 0; j < 6; j++) {
1381
1382             hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool,
1383                                    i /* Level */, &object->surfaces[j][i],pSharedHandle);
1384
1385             if(hr!= WINED3D_OK) {
1386                 /* clean up */
1387                 int k;
1388                 int l;
1389                 for (l = 0; l < j; l++) {
1390                     IWineD3DSurface_Release(object->surfaces[j][i]);
1391                 }
1392                 for (k = 0; k < i; k++) {
1393                     for (l = 0; l < 6; l++) {
1394                     IWineD3DSurface_Release(object->surfaces[l][j]);
1395                     }
1396                 }
1397
1398                 FIXME("(%p) Failed to create surface\n",object);
1399                 HeapFree(GetProcessHeap(),0,object);
1400                 *ppCubeTexture = NULL;
1401                 return hr;
1402             }
1403             IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1404             TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1405         }
1406         tmpW = max(1, tmpW >> 1);
1407     }
1408
1409     TRACE("(%p) : Created Cube Texture %p\n", This, object);
1410     *ppCubeTexture = (IWineD3DCubeTexture *) object;
1411     return WINED3D_OK;
1412 }
1413
1414 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1415     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1416     IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1417
1418     if (NULL == ppQuery) {
1419         /* Just a check to see if we support this type of query */
1420         HRESULT hr = WINED3DERR_NOTAVAILABLE;
1421         switch(Type) {
1422         case WINED3DQUERYTYPE_OCCLUSION:
1423             TRACE("(%p) occlusion query\n", This);
1424             if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1425                 hr = WINED3D_OK;
1426             else
1427                 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1428             break;
1429         case WINED3DQUERYTYPE_VCACHE:
1430         case WINED3DQUERYTYPE_RESOURCEMANAGER:
1431         case WINED3DQUERYTYPE_VERTEXSTATS:
1432         case WINED3DQUERYTYPE_EVENT:
1433         case WINED3DQUERYTYPE_TIMESTAMP:
1434         case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1435         case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1436         case WINED3DQUERYTYPE_PIPELINETIMINGS:
1437         case WINED3DQUERYTYPE_INTERFACETIMINGS:
1438         case WINED3DQUERYTYPE_VERTEXTIMINGS:
1439         case WINED3DQUERYTYPE_PIXELTIMINGS:
1440         case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1441         case WINED3DQUERYTYPE_CACHEUTILIZATION:
1442         default:
1443             FIXME("(%p) Unhandled query type %d\n", This, Type);
1444         }
1445         return hr;
1446     }
1447
1448     D3DCREATEOBJECTINSTANCE(object, Query)
1449     object->type         = Type;
1450     /* allocated the 'extended' data based on the type of query requested */
1451     switch(Type){
1452     case WINED3DQUERYTYPE_OCCLUSION:
1453         if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1454             TRACE("(%p) Allocating data for an occlusion query\n", This);
1455             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1456             GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1457             break;
1458         }
1459     case WINED3DQUERYTYPE_VCACHE:
1460     case WINED3DQUERYTYPE_RESOURCEMANAGER:
1461     case WINED3DQUERYTYPE_VERTEXSTATS:
1462     case WINED3DQUERYTYPE_EVENT:
1463     case WINED3DQUERYTYPE_TIMESTAMP:
1464     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1465     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1466     case WINED3DQUERYTYPE_PIPELINETIMINGS:
1467     case WINED3DQUERYTYPE_INTERFACETIMINGS:
1468     case WINED3DQUERYTYPE_VERTEXTIMINGS:
1469     case WINED3DQUERYTYPE_PIXELTIMINGS:
1470     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1471     case WINED3DQUERYTYPE_CACHEUTILIZATION:
1472     default:
1473         object->extendedData = 0;
1474         FIXME("(%p) Unhandled query type %d\n",This , Type);
1475     }
1476     TRACE("(%p) : Created Query %p\n", This, object);
1477     return WINED3D_OK;
1478 }
1479
1480 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1481 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS*  pPresentationParameters,                                                                   IWineD3DSwapChain** ppSwapChain,
1482                                                             IUnknown* parent,
1483                                                             D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1484                                                             D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1485     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1486
1487     HDC                     hDc;
1488     IWineD3DSwapChainImpl  *object; /** NOTE: impl ref allowed since this is a create function **/
1489     int                     num;
1490     XVisualInfo             template;
1491     GLXContext              oldContext;
1492     Drawable                oldDrawable;
1493     HRESULT                 hr = WINED3D_OK;
1494
1495     TRACE("(%p) : Created Aditional Swap Chain\n", This);
1496
1497    /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1498    * does a device hold a reference to a swap chain giving them a lifetime of the device
1499    * or does the swap chain notify the device of its destruction.
1500     *******************************/
1501
1502     /* Check the params */
1503     if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1504         ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1505         return WINED3DERR_INVALIDCALL;
1506     } else if (*pPresentationParameters->BackBufferCount > 1) {
1507         FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
1508     }
1509
1510     D3DCREATEOBJECTINSTANCE(object, SwapChain)
1511
1512     /*********************
1513     * Lookup the window Handle and the relating X window handle
1514     ********************/
1515
1516     /* Setup hwnd we are using, plus which display this equates to */
1517     object->win_handle = *(pPresentationParameters->hDeviceWindow);
1518     if (!object->win_handle) {
1519         object->win_handle = This->createParms.hFocusWindow;
1520     }
1521
1522     object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1523     if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1524         ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1525         return WINED3DERR_NOTAVAILABLE;
1526     }
1527     hDc                = GetDC(object->win_handle);
1528     object->display    = get_display(hDc);
1529     ReleaseDC(object->win_handle, hDc);
1530     TRACE("Using a display of %p %p\n", object->display, hDc);
1531
1532     if (NULL == object->display || NULL == hDc) {
1533         WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1534         return WINED3DERR_NOTAVAILABLE;
1535     }
1536
1537     if (object->win == 0) {
1538         WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1539         return WINED3DERR_NOTAVAILABLE;
1540     }
1541
1542     object->orig_width = GetSystemMetrics(SM_CXSCREEN);
1543     object->orig_height = GetSystemMetrics(SM_CYSCREEN);
1544
1545     /**
1546     * Create an opengl context for the display visual
1547     *  NOTE: the visual is chosen as the window is created and the glcontext cannot
1548     *     use different properties after that point in time. FIXME: How to handle when requested format
1549     *     doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1550     *     it chooses is identical to the one already being used!
1551      **********************************/
1552
1553     /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1554     ENTER_GL();
1555
1556     /* Create a new context for this swapchain */
1557     template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1558     /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1559     (or the best possible if none is requested) */
1560     TRACE("Found x visual ID  : %ld\n", template.visualid);
1561
1562     object->visInfo   = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1563     if (NULL == object->visInfo) {
1564         ERR("cannot really get XVisual\n");
1565         LEAVE_GL();
1566         return WINED3DERR_NOTAVAILABLE;
1567     } else {
1568         int n, value;
1569         /* Write out some debug info about the visual/s */
1570         TRACE("Using x visual ID  : %ld\n", template.visualid);
1571         TRACE("        visual info: %p\n", object->visInfo);
1572         TRACE("        num items  : %d\n", num);
1573         for (n = 0;n < num; n++) {
1574             TRACE("=====item=====: %d\n", n + 1);
1575             TRACE("   visualid      : %ld\n", object->visInfo[n].visualid);
1576             TRACE("   screen        : %d\n",  object->visInfo[n].screen);
1577             TRACE("   depth         : %u\n",  object->visInfo[n].depth);
1578             TRACE("   class         : %d\n",  object->visInfo[n].class);
1579             TRACE("   red_mask      : %ld\n", object->visInfo[n].red_mask);
1580             TRACE("   green_mask    : %ld\n", object->visInfo[n].green_mask);
1581             TRACE("   blue_mask     : %ld\n", object->visInfo[n].blue_mask);
1582             TRACE("   colormap_size : %d\n",  object->visInfo[n].colormap_size);
1583             TRACE("   bits_per_rgb  : %d\n",  object->visInfo[n].bits_per_rgb);
1584             /* log some extra glx info */
1585             glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1586             TRACE("   gl_aux_buffers  : %d\n",  value);
1587             glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1588             TRACE("   gl_buffer_size  : %d\n",  value);
1589             glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1590             TRACE("   gl_red_size  : %d\n",  value);
1591             glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1592             TRACE("   gl_green_size  : %d\n",  value);
1593             glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1594             TRACE("   gl_blue_size  : %d\n",  value);
1595             glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1596             TRACE("   gl_alpha_size  : %d\n",  value);
1597             glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1598             TRACE("   gl_depth_size  : %d\n",  value);
1599             glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1600             TRACE("   gl_stencil_size : %d\n",  value);
1601         }
1602         /* Now choose a similar visual ID*/
1603     }
1604 #ifdef USE_CONTEXT_MANAGER
1605
1606     /** TODO: use a context mamager **/
1607 #endif
1608
1609     {
1610         IWineD3DSwapChain *implSwapChain;
1611         if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1612             /* The first time around we create the context that is shared with all other swapchains and render targets */
1613             object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1614             TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1615         } else {
1616
1617             TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1618             /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1619             /* and create a new context with the implicit swapchains context as the shared context */
1620             object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1621             IWineD3DSwapChain_Release(implSwapChain);
1622         }
1623     }
1624
1625     /* Cleanup */
1626     XFree(object->visInfo);
1627     object->visInfo = NULL;
1628
1629     LEAVE_GL();
1630
1631     if (!object->glCtx) {
1632         ERR("Failed to create GLX context\n");
1633         return WINED3DERR_NOTAVAILABLE;
1634     } else {
1635         TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1636                 object->win_handle, object->glCtx, object->win, object->visInfo);
1637     }
1638
1639    /*********************
1640    * Windowed / Fullscreen
1641    *******************/
1642
1643    /**
1644    * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1645    * so we should really check to see if there is a fullscreen swapchain already
1646    * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1647     **************************************/
1648
1649    if (!*(pPresentationParameters->Windowed)) {
1650
1651         DEVMODEW devmode;
1652         HDC      hdc;
1653         int      bpp = 0;
1654
1655         /* Get info on the current display setup */
1656         hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1657         bpp = GetDeviceCaps(hdc, BITSPIXEL);
1658         DeleteDC(hdc);
1659
1660         /* Change the display settings */
1661         memset(&devmode, 0, sizeof(DEVMODEW));
1662         devmode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1663         devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1664         devmode.dmPelsWidth  = *(pPresentationParameters->BackBufferWidth);
1665         devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1666         MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1667         ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1668
1669         /* Make popup window */
1670         SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1671         SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1672                      *(pPresentationParameters->BackBufferWidth),
1673                      *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1674
1675         /* For GetDisplayMode */
1676         This->ddraw_width = devmode.dmPelsWidth;
1677         This->ddraw_height = devmode.dmPelsHeight;
1678         This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1679     }
1680
1681
1682     /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1683      *  then the corresponding dimension of the client area of the hDeviceWindow
1684      *  (or the focus window, if hDeviceWindow is NULL) is taken.
1685       **********************/
1686
1687     if (*(pPresentationParameters->Windowed) &&
1688         ((*(pPresentationParameters->BackBufferWidth)  == 0) ||
1689          (*(pPresentationParameters->BackBufferHeight) == 0))) {
1690
1691         RECT Rect;
1692         GetClientRect(object->win_handle, &Rect);
1693
1694         if (*(pPresentationParameters->BackBufferWidth) == 0) {
1695            *(pPresentationParameters->BackBufferWidth) = Rect.right;
1696            TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1697         }
1698         if (*(pPresentationParameters->BackBufferHeight) == 0) {
1699            *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1700            TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1701         }
1702     }
1703
1704    /*********************
1705    * finish off parameter initialization
1706    *******************/
1707
1708     /* Put the correct figures in the presentation parameters */
1709     TRACE("Copying across presentation parameters\n");
1710     object->presentParms.BackBufferWidth                = *(pPresentationParameters->BackBufferWidth);
1711     object->presentParms.BackBufferHeight               = *(pPresentationParameters->BackBufferHeight);
1712     object->presentParms.BackBufferFormat               = *(pPresentationParameters->BackBufferFormat);
1713     object->presentParms.BackBufferCount                = *(pPresentationParameters->BackBufferCount);
1714     object->presentParms.MultiSampleType                = *(pPresentationParameters->MultiSampleType);
1715     object->presentParms.MultiSampleQuality             = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1716     object->presentParms.SwapEffect                     = *(pPresentationParameters->SwapEffect);
1717     object->presentParms.hDeviceWindow                  = *(pPresentationParameters->hDeviceWindow);
1718     object->presentParms.Windowed                       = *(pPresentationParameters->Windowed);
1719     object->presentParms.EnableAutoDepthStencil         = *(pPresentationParameters->EnableAutoDepthStencil);
1720     object->presentParms.AutoDepthStencilFormat         = *(pPresentationParameters->AutoDepthStencilFormat);
1721     object->presentParms.Flags                          = *(pPresentationParameters->Flags);
1722     object->presentParms.FullScreen_RefreshRateInHz     = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1723     object->presentParms.PresentationInterval           = *(pPresentationParameters->PresentationInterval);
1724
1725
1726    /*********************
1727    * Create the back, front and stencil buffers
1728    *******************/
1729
1730     TRACE("calling rendertarget CB\n");
1731     hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1732                              parent,
1733                              object->presentParms.BackBufferWidth,
1734                              object->presentParms.BackBufferHeight,
1735                              object->presentParms.BackBufferFormat,
1736                              object->presentParms.MultiSampleType,
1737                              object->presentParms.MultiSampleQuality,
1738                              TRUE /* Lockable */,
1739                              &object->frontBuffer,
1740                              NULL /* pShared (always null)*/);
1741     if (object->frontBuffer != NULL)
1742         IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1743
1744     if(object->presentParms.BackBufferCount > 0) {
1745         int i;
1746
1747         object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1748         if(!object->backBuffer) {
1749             ERR("Out of memory\n");
1750
1751             if (object->frontBuffer) {
1752                 IUnknown *bufferParent;
1753                 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1754                 IUnknown_Release(bufferParent); /* once for the get parent */
1755                 if (IUnknown_Release(bufferParent) > 0) {
1756                     FIXME("(%p) Something's still holding the front buffer\n",This);
1757                 }
1758             }
1759             HeapFree(GetProcessHeap(), 0, object);
1760             return E_OUTOFMEMORY;
1761         }
1762
1763         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1764             TRACE("calling rendertarget CB\n");
1765             hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1766                                     parent,
1767                                     object->presentParms.BackBufferWidth,
1768                                     object->presentParms.BackBufferHeight,
1769                                     object->presentParms.BackBufferFormat,
1770                                     object->presentParms.MultiSampleType,
1771                                     object->presentParms.MultiSampleQuality,
1772                                     TRUE /* Lockable */,
1773                                     &object->backBuffer[i],
1774                                     NULL /* pShared (always null)*/);
1775             if(hr == WINED3D_OK && object->backBuffer[i]) {
1776                 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1777             } else {
1778                 break;
1779             }
1780         }
1781     } else {
1782         object->backBuffer = NULL;
1783     }
1784
1785     if (object->backBuffer != NULL) {
1786         ENTER_GL();
1787         glDrawBuffer(GL_BACK);
1788         checkGLcall("glDrawBuffer(GL_BACK)");
1789         LEAVE_GL();
1790     } else {
1791         /* Single buffering - draw to front buffer */
1792         ENTER_GL();
1793         glDrawBuffer(GL_FRONT);
1794         checkGLcall("glDrawBuffer(GL_FRONT)");
1795         LEAVE_GL();
1796     }
1797
1798     /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1799     if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1800         TRACE("Creating depth stencil buffer\n");
1801         if (This->depthStencilBuffer == NULL ) {
1802             hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1803                                     parent,
1804                                     object->presentParms.BackBufferWidth,
1805                                     object->presentParms.BackBufferHeight,
1806                                     object->presentParms.AutoDepthStencilFormat,
1807                                     object->presentParms.MultiSampleType,
1808                                     object->presentParms.MultiSampleQuality,
1809                                     FALSE /* FIXME: Discard */,
1810                                     &This->depthStencilBuffer,
1811                                     NULL /* pShared (always null)*/  );
1812             if (This->depthStencilBuffer != NULL)
1813                 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1814         }
1815
1816         /** TODO: A check on width, height and multisample types
1817         *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1818          ****************************/
1819         object->wantsDepthStencilBuffer = TRUE;
1820     } else {
1821         object->wantsDepthStencilBuffer = FALSE;
1822     }
1823
1824     TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1825
1826
1827    /*********************
1828    * init the default renderTarget management
1829    *******************/
1830     object->drawable     = object->win;
1831     object->render_ctx   = object->glCtx;
1832
1833     if (hr == WINED3D_OK) {
1834         /*********************
1835          * Setup some defaults and clear down the buffers
1836          *******************/
1837         ENTER_GL();
1838         /** save current context and drawable **/
1839         oldContext  = glXGetCurrentContext();
1840         oldDrawable = glXGetCurrentDrawable();
1841
1842         TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1843         if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1844             ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1845         }
1846         checkGLcall("glXMakeCurrent");
1847
1848         TRACE("Setting up the screen\n");
1849         /* Clear the screen */
1850         glClearColor(1.0, 0.0, 0.0, 0.0);
1851         checkGLcall("glClearColor");
1852         glClearIndex(0);
1853         glClearDepth(1);
1854         glClearStencil(0xffff);
1855
1856         checkGLcall("glClear");
1857
1858         glColor3f(1.0, 1.0, 1.0);
1859         checkGLcall("glColor3f");
1860
1861         glEnable(GL_LIGHTING);
1862         checkGLcall("glEnable");
1863
1864         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1865         checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1866
1867         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1868         checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1869
1870         glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1871         checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1872
1873         /* switch back to the original context (if there was one)*/
1874         if (This->swapchains) {
1875             /** TODO: restore the context and drawable **/
1876             glXMakeCurrent(object->display, oldDrawable, oldContext);
1877         }
1878
1879         /* Set the surface alignment. This never changes, so we are safe to set it once per context*/
1880         glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);
1881         checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1882         glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);
1883         checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);");
1884
1885         LEAVE_GL();
1886
1887         TRACE("Set swapchain to %p\n", object);
1888     } else { /* something went wrong so clean up */
1889         IUnknown* bufferParent;
1890         if (object->frontBuffer) {
1891
1892             IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1893             IUnknown_Release(bufferParent); /* once for the get parent */
1894             if (IUnknown_Release(bufferParent) > 0) {
1895                 FIXME("(%p) Something's still holding the front buffer\n",This);
1896             }
1897         }
1898         if (object->backBuffer) {
1899             int i;
1900             for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1901                 if(object->backBuffer[i]) {
1902                     IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1903                     IUnknown_Release(bufferParent); /* once for the get parent */
1904                     if (IUnknown_Release(bufferParent) > 0) {
1905                         FIXME("(%p) Something's still holding the back buffer\n",This);
1906                     }
1907                 }
1908             }
1909             HeapFree(GetProcessHeap(), 0, object->backBuffer);
1910             object->backBuffer = NULL;
1911         }
1912         /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1913         /* Clean up the context */
1914         /* check that we are the current context first (we shouldn't be though!) */
1915         if (object->glCtx != 0) {
1916             if(glXGetCurrentContext() == object->glCtx) {
1917                 glXMakeCurrent(object->display, None, NULL);
1918             }
1919             glXDestroyContext(object->display, object->glCtx);
1920         }
1921         HeapFree(GetProcessHeap(), 0, object);
1922
1923     }
1924
1925     return hr;
1926 }
1927
1928 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1929 static UINT     WINAPI  IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1930     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1931     TRACE("(%p)\n", This);
1932
1933     return This->NumberOfSwapChains;
1934 }
1935
1936 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1937     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1938     TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1939
1940     if(iSwapChain < This->NumberOfSwapChains) {
1941         *pSwapChain = This->swapchains[iSwapChain];
1942         IWineD3DSwapChain_AddRef(*pSwapChain);
1943         TRACE("(%p) returning %p\n", This, *pSwapChain);
1944         return WINED3D_OK;
1945     } else {
1946         TRACE("Swapchain out of range\n");
1947         *pSwapChain = NULL;
1948         return WINED3DERR_INVALIDCALL;
1949     }
1950 }
1951
1952 /*****
1953  * Vertex Declaration
1954  *****/
1955 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1956     IWineD3DDeviceImpl            *This   = (IWineD3DDeviceImpl *)iface;
1957     IWineD3DVertexDeclarationImpl *object = NULL;
1958     HRESULT hr = WINED3D_OK;
1959     TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1960     D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1961     object->allFVF = 0;
1962
1963     hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1964
1965     return hr;
1966 }
1967
1968 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1969 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1970     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1971     IWineD3DVertexShaderImpl *object;  /* NOTE: impl usage is ok, this is a create */
1972     HRESULT hr = WINED3D_OK;
1973     D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1974     object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1975
1976     TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1977
1978     /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1979     /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1980     if (pDeclaration != NULL) {
1981         IWineD3DVertexDeclaration *vertexDeclaration;
1982         hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1983         if (WINED3D_OK == hr) {
1984             TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1985             object->vertexDeclaration = vertexDeclaration;
1986         } else {
1987             FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1988             IWineD3DVertexShader_Release(*ppVertexShader);
1989             return WINED3DERR_INVALIDCALL;
1990         }
1991     }
1992
1993     hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1994
1995     if (WINED3D_OK != hr) {
1996         FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1997         IWineD3DVertexShader_Release(*ppVertexShader);
1998         return WINED3DERR_INVALIDCALL;
1999     }
2000
2001 #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. */
2002     if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
2003         /* Foo */
2004     } else {
2005         /* Bar */
2006     }
2007
2008 #endif
2009
2010     return WINED3D_OK;
2011 }
2012
2013 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
2014     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2015     IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
2016     HRESULT hr = WINED3D_OK;
2017
2018     D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
2019     object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
2020     hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
2021     if (WINED3D_OK == hr) {
2022         TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
2023     } else {
2024         WARN("(%p) : Failed to create pixel shader\n", This);
2025     }
2026
2027     return hr;
2028 }
2029
2030 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
2031     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2032     IWineD3DPaletteImpl *object;
2033     HRESULT hr;
2034     TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
2035
2036     /* Create the new object */
2037     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
2038     if(!object) {
2039         ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2040         return E_OUTOFMEMORY;
2041     }
2042
2043     object->lpVtbl = &IWineD3DPalette_Vtbl;
2044     object->ref = 1;
2045     object->Flags = Flags;
2046     object->parent = Parent;
2047     object->wineD3DDevice = This;
2048     object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
2049         
2050     object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
2051
2052     if(!object->hpal) {
2053         HeapFree( GetProcessHeap(), 0, object);
2054         return E_OUTOFMEMORY;
2055     }
2056
2057     hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
2058     if(FAILED(hr)) {
2059         IWineD3DPalette_Release((IWineD3DPalette *) object);
2060         return hr;
2061     }
2062
2063     *Palette = (IWineD3DPalette *) object;
2064
2065     return WINED3D_OK;
2066 }
2067
2068 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
2069     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2070     IWineD3DSwapChainImpl *swapchain;
2071
2072     TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
2073     if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2074
2075     /* TODO: Test if OpenGL is compiled in and loaded */
2076
2077     /* Setup the implicit swapchain */
2078     TRACE("Creating implicit swapchain\n");
2079     if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2080         WARN("Failed to create implicit swapchain\n");
2081         return WINED3DERR_INVALIDCALL;
2082     }
2083
2084     This->NumberOfSwapChains = 1;
2085     This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2086     if(!This->swapchains) {
2087         ERR("Out of memory!\n");
2088         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2089         return E_OUTOFMEMORY;
2090     }
2091     This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2092
2093     if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2094         TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2095         This->renderTarget = swapchain->backBuffer[0];
2096     }
2097     else {
2098         TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2099         This->renderTarget = swapchain->frontBuffer;
2100     }
2101     IWineD3DSurface_AddRef(This->renderTarget);
2102     /* Depth Stencil support */
2103     This->stencilBufferTarget = This->depthStencilBuffer;
2104     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
2105         set_depth_stencil_fbo(iface, This->depthStencilBuffer);
2106     }
2107     if (NULL != This->stencilBufferTarget) {
2108         IWineD3DSurface_AddRef(This->stencilBufferTarget);
2109     }
2110
2111     /* Set up some starting GL setup */
2112     ENTER_GL();
2113     /*
2114     * Initialize openGL extension related variables
2115     *  with Default values
2116     */
2117
2118     ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2119     /* Setup all the devices defaults */
2120     IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2121 #if 0
2122     IWineD3DImpl_CheckGraphicsMemory();
2123 #endif
2124     LEAVE_GL();
2125
2126     /* Initialize our list of GLSL programs */
2127     list_init(&This->glsl_shader_progs);
2128
2129     { /* Set a default viewport */
2130         WINED3DVIEWPORT vp;
2131         vp.X      = 0;
2132         vp.Y      = 0;
2133         vp.Width  = *(pPresentationParameters->BackBufferWidth);
2134         vp.Height = *(pPresentationParameters->BackBufferHeight);
2135         vp.MinZ   = 0.0f;
2136         vp.MaxZ   = 1.0f;
2137         IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2138     }
2139
2140     /* Initialize the current view state */
2141     This->modelview_valid = 1;
2142     This->proj_valid = 0;
2143     This->view_ident = 1;
2144     This->last_was_rhw = 0;
2145     glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2146     TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2147
2148     /* Clear the screen */
2149     IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
2150
2151     This->d3d_initialized = TRUE;
2152     return WINED3D_OK;
2153 }
2154
2155 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface) {
2156     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2157     int sampler;
2158     IUnknown* swapChainParent;
2159     uint i;
2160     TRACE("(%p)\n", This);
2161
2162     if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2163
2164     /* Delete the mouse cursor texture */
2165     if(This->cursorTexture) {
2166         ENTER_GL();
2167         glDeleteTextures(1, &This->cursorTexture);
2168         LEAVE_GL();
2169         This->cursorTexture = 0;
2170     }
2171
2172     for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2173         IWineD3DDevice_SetTexture(iface, sampler, NULL);
2174     }
2175
2176     /* Release the buffers (with sanity checks)*/
2177     TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2178     if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2179         if(This->depthStencilBuffer != This->stencilBufferTarget)
2180             FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2181     }
2182     This->stencilBufferTarget = NULL;
2183
2184     TRACE("Releasing the render target at %p\n", This->renderTarget);
2185     if(IWineD3DSurface_Release(This->renderTarget) >0){
2186           /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2187     }
2188     TRACE("Setting rendertarget to NULL\n");
2189     This->renderTarget = NULL;
2190
2191     if (This->depthStencilBuffer) {
2192         if(D3DCB_DestroyDepthStencilSurface > 0) {
2193             FIXME("(%p) Something's still holding the depthStencilBuffer\n", This);
2194         }
2195         This->depthStencilBuffer = NULL;
2196     }
2197
2198     for(i=0; i < This->NumberOfSwapChains; i++) {
2199         TRACE("Releasing the implicit swapchain %d\n", i);
2200         /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
2201         IWineD3DSwapChain_GetParent(This->swapchains[i], &swapChainParent);
2202         IUnknown_Release(swapChainParent);           /* once for the get parent */
2203         if (IUnknown_Release(swapChainParent)  > 0) {  /* the second time for when it was created */
2204             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2205         }
2206     }
2207
2208     HeapFree(GetProcessHeap(), 0, This->swapchains);
2209     This->swapchains = NULL;
2210     This->NumberOfSwapChains = 0;
2211
2212     This->d3d_initialized = FALSE;
2213     return WINED3D_OK;
2214 }
2215
2216 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2217     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2218     TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2219
2220     /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2221      * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2222      * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
2223      * separately.
2224      */
2225     This->ddraw_fullscreen = fullscreen;
2226 }
2227
2228 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2229     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2230
2231     DEVMODEW DevModeW;
2232     int i;
2233     const PixelFormatDesc *formatDesc  = getFormatDescEntry(pixelformat);
2234
2235     TRACE("(%p)->(%x,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2236
2237     for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2238         /* Ignore some modes if a description was passed */
2239         if ( (Width > 0)  && (Width != DevModeW.dmPelsWidth)) continue;
2240         if ( (Height > 0)  && (Height != DevModeW.dmPelsHeight)) continue;
2241         if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2242
2243         TRACE("Enumerating %dx%d@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2244
2245         if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2246             return D3D_OK;
2247     }
2248
2249     return D3D_OK;
2250 }
2251
2252 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2253     DEVMODEW devmode;
2254     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2255     LONG ret;
2256     const PixelFormatDesc *formatDesc  = getFormatDescEntry(pMode->Format);
2257
2258     TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2259
2260     /* Resize the screen even without a window:
2261      * The app could have unset it with SetCooperativeLevel, but not called
2262      * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2263      * but we don't have any hwnd
2264      */
2265
2266     devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2267     devmode.dmBitsPerPel = formatDesc->bpp * 8;
2268     if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2269     devmode.dmPelsWidth  = pMode->Width;
2270     devmode.dmPelsHeight = pMode->Height;
2271
2272     devmode.dmDisplayFrequency = pMode->RefreshRate;
2273     if (pMode->RefreshRate != 0)  {
2274         devmode.dmFields |= DM_DISPLAYFREQUENCY;
2275     }
2276
2277     /* Only change the mode if necessary */
2278     if( (This->ddraw_width == pMode->Width) &&
2279         (This->ddraw_height == pMode->Height) &&
2280         (This->ddraw_format == pMode->Format) &&
2281         (pMode->RefreshRate == 0) ) {
2282         return D3D_OK;
2283     }
2284
2285     ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2286     if (ret != DISP_CHANGE_SUCCESSFUL) {
2287         if(devmode.dmDisplayFrequency != 0) {
2288             WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2289             devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2290             devmode.dmDisplayFrequency = 0;
2291             ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2292         }
2293         if(ret != DISP_CHANGE_SUCCESSFUL) {
2294             return DDERR_INVALIDMODE;
2295         }
2296     }
2297
2298     /* Store the new values */
2299     This->ddraw_width = pMode->Width;
2300     This->ddraw_height = pMode->Height;
2301     This->ddraw_format = pMode->Format;
2302
2303     /* Only do this with a window of course */
2304     if(This->ddraw_window)
2305       MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2306
2307     return WINED3D_OK;
2308 }
2309
2310 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2311    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2312    *ppD3D= This->wineD3D;
2313    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
2314    IWineD3D_AddRef(*ppD3D);
2315    return WINED3D_OK;
2316 }
2317
2318 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2319     /** NOTE: There's a probably  a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
2320     * into the video ram as possible and seeing how many fit
2321     * you can also get the correct initial value from nvidia and ATI's driver via X
2322     * texture memory is video memory + AGP memory
2323     *******************/
2324     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2325     static BOOL showfixmes = TRUE;
2326     if (showfixmes) {
2327         FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2328          (wined3d_settings.emulated_textureram/(1024*1024)),
2329          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2330          showfixmes = FALSE;
2331     }
2332     TRACE("(%p) : simulating %dMB, returning %dMB left\n",  This,
2333          (wined3d_settings.emulated_textureram/(1024*1024)),
2334          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2335     /* return simulated texture memory left */
2336     return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2337 }
2338
2339
2340
2341 /*****
2342  * Get / Set FVF
2343  *****/
2344 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2345     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2346     HRESULT hr = WINED3D_OK;
2347
2348     /* Update the current state block */
2349     This->updateStateBlock->fvf              = fvf;
2350     This->updateStateBlock->changed.fvf      = TRUE;
2351     This->updateStateBlock->set.fvf          = TRUE;
2352
2353     TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2354     return hr;
2355 }
2356
2357
2358 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2359     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2360     TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2361     *pfvf = This->stateBlock->fvf;
2362     return WINED3D_OK;
2363 }
2364
2365 /*****
2366  * Get / Set Stream Source
2367  *****/
2368 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2369         IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
2370     IWineD3DVertexBuffer     *oldSrc;
2371
2372     /**TODO: instance and index data, see
2373     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2374     and
2375     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2376      **************/
2377
2378     /* D3d9 only, but shouldn't  hurt d3d8 */
2379     UINT streamFlags;
2380
2381     streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2382     if (streamFlags) {
2383         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2384            FIXME("stream index data not supported\n");
2385         }
2386         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2387            FIXME("stream instance data not supported\n");
2388         }
2389     }
2390
2391     StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2392
2393     if (StreamNumber >= MAX_STREAMS) {
2394         WARN("Stream out of range %d\n", StreamNumber);
2395         return WINED3DERR_INVALIDCALL;
2396     }
2397
2398     oldSrc = This->stateBlock->streamSource[StreamNumber];
2399     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2400
2401     This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2402     This->updateStateBlock->set.streamSource[StreamNumber]     = TRUE;
2403     This->updateStateBlock->streamStride[StreamNumber]         = Stride;
2404     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
2405     This->updateStateBlock->streamOffset[StreamNumber]         = OffsetInBytes;
2406     This->updateStateBlock->streamFlags[StreamNumber]          = streamFlags;
2407
2408     /* Handle recording of state blocks */
2409     if (This->isRecordingState) {
2410         TRACE("Recording... not performing anything\n");
2411         return WINED3D_OK;
2412     }
2413
2414     /* Same stream object: no action */
2415     if (oldSrc == pStreamData)
2416         return WINED3D_OK;
2417
2418     /* Need to do a getParent and pass the reffs up */
2419     /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2420     which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2421     so for now, just count internally   */
2422     if (pStreamData != NULL) {
2423         IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2424         if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2425             WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2426         }
2427         vbImpl->stream = StreamNumber;
2428         vbImpl->Flags |= VBFLAG_STREAM;
2429         IWineD3DVertexBuffer_AddRef(pStreamData);
2430     }
2431     if (oldSrc != NULL) {
2432         ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2433         IWineD3DVertexBuffer_Release(oldSrc);
2434     }
2435
2436     return WINED3D_OK;
2437 }
2438
2439 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2440     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2441     UINT streamFlags;
2442
2443     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2444            This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2445
2446
2447     streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2448     if (streamFlags) {
2449         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2450            FIXME("stream index data not supported\n");
2451         }
2452         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2453             FIXME("stream instance data not supported\n");
2454         }
2455     }
2456
2457     StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2458
2459     if (StreamNumber >= MAX_STREAMS) {
2460         WARN("Stream out of range %d\n", StreamNumber);
2461         return WINED3DERR_INVALIDCALL;
2462     }
2463     *pStream = This->stateBlock->streamSource[StreamNumber];
2464     *pStride = This->stateBlock->streamStride[StreamNumber];
2465     if (pOffset) {
2466         *pOffset = This->stateBlock->streamOffset[StreamNumber];
2467     }
2468
2469      if (*pStream == NULL) {
2470         FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2471         return  WINED3DERR_INVALIDCALL;
2472     }
2473
2474     IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2475     return WINED3D_OK;
2476 }
2477
2478 /*Should be quite easy, just an extension of vertexdata
2479 ref...
2480 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2481
2482 The divider is a bit odd though
2483
2484 VertexOffset = StartVertex / Divider * StreamStride +
2485                VertexIndex / Divider * StreamStride + StreamOffset
2486
2487 */
2488 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
2489     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2490
2491     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2492     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
2493
2494     This->updateStateBlock->changed.streamFreq[StreamNumber]  = TRUE;
2495     This->updateStateBlock->set.streamFreq[StreamNumber]      = TRUE;
2496     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
2497
2498     if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2499         FIXME("Stream indexing not fully supported\n");
2500     }
2501
2502     return WINED3D_OK;
2503 }
2504
2505 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
2506     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2507
2508     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2509     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2510
2511     TRACE("(%p) : returning %d\n", This, *Divider);
2512
2513     return WINED3D_OK;
2514 }
2515
2516 /*****
2517  * Get / Set & Multiply Transform
2518  *****/
2519 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2520     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2521
2522     /* Most of this routine, comments included copied from ddraw tree initially: */
2523     TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2524
2525     /* Handle recording of state blocks */
2526     if (This->isRecordingState) {
2527         TRACE("Recording... not performing anything\n");
2528         This->updateStateBlock->changed.transform[d3dts] = TRUE;
2529         This->updateStateBlock->set.transform[d3dts]     = TRUE;
2530         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2531         return WINED3D_OK;
2532     }
2533
2534     /*
2535      * If the new matrix is the same as the current one,
2536      * we cut off any further processing. this seems to be a reasonable
2537      * optimization because as was noticed, some apps (warcraft3 for example)
2538      * tend towards setting the same matrix repeatedly for some reason.
2539      *
2540      * From here on we assume that the new matrix is different, wherever it matters.
2541      */
2542     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2543         TRACE("The app is setting the same matrix over again\n");
2544         return WINED3D_OK;
2545     } else {
2546         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2547     }
2548
2549     /*
2550        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2551        where ViewMat = Camera space, WorldMat = world space.
2552
2553        In OpenGL, camera and world space is combined into GL_MODELVIEW
2554        matrix.  The Projection matrix stay projection matrix.
2555      */
2556
2557     /* Capture the times we can just ignore the change for now */
2558     if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2559         This->modelview_valid = FALSE;
2560         return WINED3D_OK;
2561
2562     } else if (d3dts == WINED3DTS_PROJECTION) {
2563         This->proj_valid = FALSE;
2564         return WINED3D_OK;
2565
2566     } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2567         /* Indexed Vertex Blending Matrices 256 -> 511  */
2568         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2569         FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2570         return WINED3D_OK;
2571     }
2572
2573     /* Now we really are going to have to change a matrix */
2574     ENTER_GL();
2575
2576     if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2577         /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2578     } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2579         unsigned int k;
2580
2581         /* If we are changing the View matrix, reset the light and clipping planes to the new view
2582          * NOTE: We have to reset the positions even if the light/plane is not currently
2583          *       enabled, since the call to enable it will not reset the position.
2584          * NOTE2: Apparently texture transforms do NOT need reapplying
2585          */
2586
2587         PLIGHTINFOEL *lightChain = NULL;
2588         This->modelview_valid = FALSE;
2589         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2590
2591         glMatrixMode(GL_MODELVIEW);
2592         checkGLcall("glMatrixMode(GL_MODELVIEW)");
2593         glPushMatrix();
2594         glLoadMatrixf((const float *)lpmatrix);
2595         checkGLcall("glLoadMatrixf(...)");
2596
2597         /* Reset lights */
2598         lightChain = This->stateBlock->lights;
2599         while (lightChain && lightChain->glIndex != -1) {
2600             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2601             checkGLcall("glLightfv posn");
2602             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2603             checkGLcall("glLightfv dirn");
2604             lightChain = lightChain->next;
2605         }
2606
2607         /* Reset Clipping Planes if clipping is enabled */
2608         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2609             glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2610             checkGLcall("glClipPlane");
2611         }
2612         glPopMatrix();
2613
2614     } else { /* What was requested!?? */
2615         WARN("invalid matrix specified: %i\n", d3dts);
2616     }
2617
2618     /* Release lock, all done */
2619     LEAVE_GL();
2620     return WINED3D_OK;
2621
2622 }
2623 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2624     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2625     TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2626     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2627     return WINED3D_OK;
2628 }
2629
2630 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2631     WINED3DMATRIX *mat = NULL;
2632     WINED3DMATRIX temp;
2633
2634     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2635      * below means it will be recorded in a state block change, but it
2636      * works regardless where it is recorded.
2637      * If this is found to be wrong, change to StateBlock.
2638      */
2639     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2640     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2641
2642     if (State < HIGHEST_TRANSFORMSTATE)
2643     {
2644         mat = &This->updateStateBlock->transforms[State];
2645     } else {
2646         FIXME("Unhandled transform state!!\n");
2647     }
2648
2649     multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2650
2651     /* Apply change via set transform - will reapply to eg. lights this way */
2652     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2653 }
2654
2655 /*****
2656  * Get / Set Light
2657  *****/
2658 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2659    you can reference any indexes you want as long as that number max are enabled at any
2660    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2661    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2662    but when recording, just build a chain pretty much of commands to be replayed.                  */
2663
2664 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2665     float rho;
2666     PLIGHTINFOEL *object, *temp;
2667
2668     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2669     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2670
2671     /* If recording state block, just add to end of lights chain */
2672     if (This->isRecordingState) {
2673         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2674         if (NULL == object) {
2675             return WINED3DERR_OUTOFVIDEOMEMORY;
2676         }
2677         memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2678         object->OriginalIndex = Index;
2679         object->glIndex = -1;
2680         object->changed = TRUE;
2681
2682         /* Add to the END of the chain of lights changes to be replayed */
2683         if (This->updateStateBlock->lights == NULL) {
2684             This->updateStateBlock->lights = object;
2685         } else {
2686             temp = This->updateStateBlock->lights;
2687             while (temp->next != NULL) temp=temp->next;
2688             temp->next = object;
2689         }
2690         TRACE("Recording... not performing anything more\n");
2691         return WINED3D_OK;
2692     }
2693
2694     /* Ok, not recording any longer so do real work */
2695     object = This->stateBlock->lights;
2696     while (object != NULL && object->OriginalIndex != Index) object = object->next;
2697
2698     /* If we didn't find it in the list of lights, time to add it */
2699     if (object == NULL) {
2700         PLIGHTINFOEL *insertAt,*prevPos;
2701
2702         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2703         if (NULL == object) {
2704             return WINED3DERR_OUTOFVIDEOMEMORY;
2705         }
2706         object->OriginalIndex = Index;
2707         object->glIndex = -1;
2708
2709         /* Add it to the front of list with the idea that lights will be changed as needed
2710            BUT after any lights currently assigned GL indexes                             */
2711         insertAt = This->stateBlock->lights;
2712         prevPos  = NULL;
2713         while (insertAt != NULL && insertAt->glIndex != -1) {
2714             prevPos  = insertAt;
2715             insertAt = insertAt->next;
2716         }
2717
2718         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2719             This->stateBlock->lights = object;
2720         } else if (insertAt == NULL) { /* End of list */
2721             prevPos->next = object;
2722             object->prev = prevPos;
2723         } else { /* Middle of chain */
2724             if (prevPos == NULL) {
2725                 This->stateBlock->lights = object;
2726             } else {
2727                 prevPos->next = object;
2728             }
2729             object->prev = prevPos;
2730             object->next = insertAt;
2731             insertAt->prev = object;
2732         }
2733     }
2734
2735     /* Initialize the object */
2736     TRACE("Light %d setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2737           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2738           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2739           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2740     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2741           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2742     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2743
2744     /* Save away the information */
2745     memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2746
2747     switch (pLight->Type) {
2748     case WINED3DLIGHT_POINT:
2749         /* Position */
2750         object->lightPosn[0] = pLight->Position.x;
2751         object->lightPosn[1] = pLight->Position.y;
2752         object->lightPosn[2] = pLight->Position.z;
2753         object->lightPosn[3] = 1.0f;
2754         object->cutoff = 180.0f;
2755         /* FIXME: Range */
2756         break;
2757
2758     case WINED3DLIGHT_DIRECTIONAL:
2759         /* Direction */
2760         object->lightPosn[0] = -pLight->Direction.x;
2761         object->lightPosn[1] = -pLight->Direction.y;
2762         object->lightPosn[2] = -pLight->Direction.z;
2763         object->lightPosn[3] = 0.0;
2764         object->exponent     = 0.0f;
2765         object->cutoff       = 180.0f;
2766         break;
2767
2768     case WINED3DLIGHT_SPOT:
2769         /* Position */
2770         object->lightPosn[0] = pLight->Position.x;
2771         object->lightPosn[1] = pLight->Position.y;
2772         object->lightPosn[2] = pLight->Position.z;
2773         object->lightPosn[3] = 1.0;
2774
2775         /* Direction */
2776         object->lightDirn[0] = pLight->Direction.x;
2777         object->lightDirn[1] = pLight->Direction.y;
2778         object->lightDirn[2] = pLight->Direction.z;
2779         object->lightDirn[3] = 1.0;
2780
2781         /*
2782          * opengl-ish and d3d-ish spot lights use too different models for the
2783          * light "intensity" as a function of the angle towards the main light direction,
2784          * so we only can approximate very roughly.
2785          * however spot lights are rather rarely used in games (if ever used at all).
2786          * furthermore if still used, probably nobody pays attention to such details.
2787          */
2788         if (pLight->Falloff == 0) {
2789             rho = 6.28f;
2790         } else {
2791             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2792         }
2793         if (rho < 0.0001) rho = 0.0001f;
2794         object->exponent = -0.3/log(cos(rho/2));
2795         if (object->exponent > 128.0) {
2796                 object->exponent = 128.0;
2797         }
2798         object->cutoff = pLight->Phi*90/M_PI;
2799
2800         /* FIXME: Range */
2801         break;
2802
2803     default:
2804         FIXME("Unrecognized light type %d\n", pLight->Type);
2805     }
2806
2807     /* Update the live definitions if the light is currently assigned a glIndex */
2808     if (object->glIndex != -1) {
2809         setup_light(iface, object->glIndex, object);
2810     }
2811     return WINED3D_OK;
2812 }
2813
2814 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2815     PLIGHTINFOEL *lightInfo = NULL;
2816     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2817     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2818
2819     /* Locate the light in the live lights */
2820     lightInfo = This->stateBlock->lights;
2821     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2822
2823     if (lightInfo == NULL) {
2824         TRACE("Light information requested but light not defined\n");
2825         return WINED3DERR_INVALIDCALL;
2826     }
2827
2828     memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2829     return WINED3D_OK;
2830 }
2831
2832 /*****
2833  * Get / Set Light Enable
2834  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2835  *****/
2836 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2837     PLIGHTINFOEL *lightInfo = NULL;
2838     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2839     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2840
2841     /* Tests show true = 128...not clear why */
2842
2843     Enable = Enable? 128: 0;
2844
2845     /* If recording state block, just add to end of lights chain with changedEnable set to true */
2846     if (This->isRecordingState) {
2847         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2848         if (NULL == lightInfo) {
2849             return WINED3DERR_OUTOFVIDEOMEMORY;
2850         }
2851         lightInfo->OriginalIndex = Index;
2852         lightInfo->glIndex = -1;
2853         lightInfo->enabledChanged = TRUE;
2854         lightInfo->lightEnabled = Enable;
2855
2856         /* Add to the END of the chain of lights changes to be replayed */
2857         if (This->updateStateBlock->lights == NULL) {
2858             This->updateStateBlock->lights = lightInfo;
2859         } else {
2860             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2861             while (temp->next != NULL) temp=temp->next;
2862             temp->next = lightInfo;
2863         }
2864         TRACE("Recording... not performing anything more\n");
2865         return WINED3D_OK;
2866     }
2867
2868     /* Not recording... So, locate the light in the live lights */
2869     lightInfo = This->stateBlock->lights;
2870     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2871
2872     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2873     if (lightInfo == NULL) {
2874
2875         TRACE("Light enabled requested but light not defined, so defining one!\n");
2876         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2877
2878         /* Search for it again! Should be fairly quick as near head of list */
2879         lightInfo = This->stateBlock->lights;
2880         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2881         if (lightInfo == NULL) {
2882             FIXME("Adding default lights has failed dismally\n");
2883             return WINED3DERR_INVALIDCALL;
2884         }
2885     }
2886
2887     /* OK, we now have a light... */
2888     if (!Enable) {
2889
2890         /* If we are disabling it, check it was enabled, and
2891            still only do something if it has assigned a glIndex (which it should have!)   */
2892         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2893             TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2894             ENTER_GL();
2895             glDisable(GL_LIGHT0 + lightInfo->glIndex);
2896             checkGLcall("glDisable GL_LIGHT0+Index");
2897             LEAVE_GL();
2898         } else {
2899             TRACE("Nothing to do as light was not enabled\n");
2900         }
2901         lightInfo->lightEnabled = Enable;
2902     } else {
2903
2904         /* We are enabling it. If it is enabled, it's really simple */
2905         if (lightInfo->lightEnabled) {
2906             /* nop */
2907             TRACE("Nothing to do as light was enabled\n");
2908
2909         /* If it already has a glIndex, it's still simple */
2910         } else if (lightInfo->glIndex != -1) {
2911             TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2912             lightInfo->lightEnabled = Enable;
2913             ENTER_GL();
2914             glEnable(GL_LIGHT0 + lightInfo->glIndex);
2915             checkGLcall("glEnable GL_LIGHT0+Index already setup");
2916             LEAVE_GL();
2917
2918         /* Otherwise got to find space - lights are ordered gl indexes first */
2919         } else {
2920             PLIGHTINFOEL *bsf  = NULL;
2921             PLIGHTINFOEL *pos  = This->stateBlock->lights;
2922             PLIGHTINFOEL *prev = NULL;
2923             int           Index= 0;
2924             int           glIndex = -1;
2925
2926             /* Try to minimize changes as much as possible */
2927             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2928
2929                 /* Try to remember which index can be replaced if necessary */
2930                 if (bsf==NULL && !pos->lightEnabled) {
2931                     /* Found a light we can replace, save as best replacement */
2932                     bsf = pos;
2933                 }
2934
2935                 /* Step to next space */
2936                 prev = pos;
2937                 pos = pos->next;
2938                 Index ++;
2939             }
2940
2941             /* If we have too many active lights, fail the call */
2942             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2943                 FIXME("Program requests too many concurrent lights\n");
2944                 return WINED3DERR_INVALIDCALL;
2945
2946             /* If we have allocated all lights, but not all are enabled,
2947                reuse one which is not enabled                           */
2948             } else if (Index == This->maxConcurrentLights) {
2949                 /* use bsf - Simply swap the new light and the BSF one */
2950                 PLIGHTINFOEL *bsfNext = bsf->next;
2951                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2952
2953                 /* Sort out ends */
2954                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2955                 if (bsf->prev != NULL) {
2956                     bsf->prev->next = lightInfo;
2957                 } else {
2958                     This->stateBlock->lights = lightInfo;
2959                 }
2960
2961                 /* If not side by side, lots of chains to update */
2962                 if (bsf->next != lightInfo) {
2963                     lightInfo->prev->next = bsf;
2964                     bsf->next->prev = lightInfo;
2965                     bsf->next       = lightInfo->next;
2966                     bsf->prev       = lightInfo->prev;
2967                     lightInfo->next = bsfNext;
2968                     lightInfo->prev = bsfPrev;
2969
2970                 } else {
2971                     /* Simple swaps */
2972                     bsf->prev = lightInfo;
2973                     bsf->next = lightInfo->next;
2974                     lightInfo->next = bsf;
2975                     lightInfo->prev = bsfPrev;
2976                 }
2977
2978
2979                 /* Update states */
2980                 glIndex = bsf->glIndex;
2981                 bsf->glIndex = -1;
2982                 lightInfo->glIndex = glIndex;
2983                 lightInfo->lightEnabled = Enable;
2984
2985                 /* Finally set up the light in gl itself */
2986                 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
2987                 ENTER_GL();
2988                 setup_light(iface, glIndex, lightInfo);
2989                 glEnable(GL_LIGHT0 + glIndex);
2990                 checkGLcall("glEnable GL_LIGHT0 new setup");
2991                 LEAVE_GL();
2992
2993             /* If we reached the end of the allocated lights, with space in the
2994                gl lights, setup a new light                                     */
2995             } else if (pos->glIndex == -1) {
2996
2997                 /* We reached the end of the allocated gl lights, so already
2998                     know the index of the next one!                          */
2999                 glIndex = Index;
3000                 lightInfo->glIndex = glIndex;
3001                 lightInfo->lightEnabled = Enable;
3002
3003                 /* In an ideal world, it's already in the right place */
3004                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
3005                    /* No need to move it */
3006                 } else {
3007                     /* Remove this light from the list */
3008                     lightInfo->prev->next = lightInfo->next;
3009                     if (lightInfo->next != NULL) {
3010                         lightInfo->next->prev = lightInfo->prev;
3011                     }
3012
3013                     /* Add in at appropriate place (inbetween prev and pos) */
3014                     lightInfo->prev = prev;
3015                     lightInfo->next = pos;
3016                     if (prev == NULL) {
3017                         This->stateBlock->lights = lightInfo;
3018                     } else {
3019                         prev->next = lightInfo;
3020                     }
3021                     if (pos != NULL) {
3022                         pos->prev = lightInfo;
3023                     }
3024                 }
3025
3026                 /* Finally set up the light in gl itself */
3027                 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
3028                 ENTER_GL();
3029                 setup_light(iface, glIndex, lightInfo);
3030                 glEnable(GL_LIGHT0 + glIndex);
3031                 checkGLcall("glEnable GL_LIGHT0 new setup");
3032                 LEAVE_GL();
3033
3034             }
3035         }
3036     }
3037     return WINED3D_OK;
3038 }
3039
3040 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3041
3042     PLIGHTINFOEL *lightInfo = NULL;
3043     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3044     TRACE("(%p) : for idx(%d)\n", This, Index);
3045
3046     /* Locate the light in the live lights */
3047     lightInfo = This->stateBlock->lights;
3048     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3049
3050     if (lightInfo == NULL) {
3051         TRACE("Light enabled state requested but light not defined\n");
3052         return WINED3DERR_INVALIDCALL;
3053     }
3054     *pEnable = lightInfo->lightEnabled;
3055     return WINED3D_OK;
3056 }
3057
3058 /*****
3059  * Get / Set Clip Planes
3060  *****/
3061 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3062     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3063     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
3064
3065     /* Validate Index */
3066     if (Index >= GL_LIMITS(clipplanes)) {
3067         TRACE("Application has requested clipplane this device doesn't support\n");
3068         return WINED3DERR_INVALIDCALL;
3069     }
3070
3071     This->updateStateBlock->changed.clipplane[Index] = TRUE;
3072     This->updateStateBlock->set.clipplane[Index] = TRUE;
3073     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3074     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3075     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3076     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3077
3078     /* Handle recording of state blocks */
3079     if (This->isRecordingState) {
3080         TRACE("Recording... not performing anything\n");
3081         return WINED3D_OK;
3082     }
3083
3084     /* Apply it */
3085
3086     ENTER_GL();
3087
3088     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3089     glMatrixMode(GL_MODELVIEW);
3090     glPushMatrix();
3091     glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3092
3093     TRACE("Clipplane [%f,%f,%f,%f]\n",
3094           This->updateStateBlock->clipplane[Index][0],
3095           This->updateStateBlock->clipplane[Index][1],
3096           This->updateStateBlock->clipplane[Index][2],
3097           This->updateStateBlock->clipplane[Index][3]);
3098     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3099     checkGLcall("glClipPlane");
3100
3101     glPopMatrix();
3102     LEAVE_GL();
3103
3104     return WINED3D_OK;
3105 }
3106
3107 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3108     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3109     TRACE("(%p) : for idx %d\n", This, Index);
3110
3111     /* Validate Index */
3112     if (Index >= GL_LIMITS(clipplanes)) {
3113         TRACE("Application has requested clipplane this device doesn't support\n");
3114         return WINED3DERR_INVALIDCALL;
3115     }
3116
3117     pPlane[0] = This->stateBlock->clipplane[Index][0];
3118     pPlane[1] = This->stateBlock->clipplane[Index][1];
3119     pPlane[2] = This->stateBlock->clipplane[Index][2];
3120     pPlane[3] = This->stateBlock->clipplane[Index][3];
3121     return WINED3D_OK;
3122 }
3123
3124 /*****
3125  * Get / Set Clip Plane Status
3126  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3127  *****/
3128 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3129     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3130     FIXME("(%p) : stub\n", This);
3131     if (NULL == pClipStatus) {
3132       return WINED3DERR_INVALIDCALL;
3133     }
3134     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3135     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3136     return WINED3D_OK;
3137 }
3138
3139 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3140     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3141     FIXME("(%p) : stub\n", This);
3142     if (NULL == pClipStatus) {
3143       return WINED3DERR_INVALIDCALL;
3144     }
3145     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3146     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3147     return WINED3D_OK;
3148 }
3149
3150 /*****
3151  * Get / Set Material
3152  *****/
3153 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3154     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3155
3156     This->updateStateBlock->changed.material = TRUE;
3157     This->updateStateBlock->set.material = TRUE;
3158     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3159
3160     /* Handle recording of state blocks */
3161     if (This->isRecordingState) {
3162         TRACE("Recording... not performing anything\n");
3163         return WINED3D_OK;
3164     }
3165
3166     ENTER_GL();
3167     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3168         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3169     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3170         pMaterial->Ambient.b, pMaterial->Ambient.a);
3171     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3172         pMaterial->Specular.b, pMaterial->Specular.a);
3173     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3174         pMaterial->Emissive.b, pMaterial->Emissive.a);
3175     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3176
3177     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3178     checkGLcall("glMaterialfv(GL_AMBIENT)");
3179     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3180     checkGLcall("glMaterialfv(GL_DIFFUSE)");
3181
3182     /* Only change material color if specular is enabled, otherwise it is set to black */
3183     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3184        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3185        checkGLcall("glMaterialfv(GL_SPECULAR");
3186     } else {
3187        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3188        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3189        checkGLcall("glMaterialfv(GL_SPECULAR");
3190     }
3191     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3192     checkGLcall("glMaterialfv(GL_EMISSION)");
3193     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3194     checkGLcall("glMaterialf(GL_SHININESS");
3195
3196     LEAVE_GL();
3197     return WINED3D_OK;
3198 }
3199
3200 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3201     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3202     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3203     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3204         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3205     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3206         pMaterial->Ambient.b, pMaterial->Ambient.a);
3207     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3208         pMaterial->Specular.b, pMaterial->Specular.a);
3209     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3210         pMaterial->Emissive.b, pMaterial->Emissive.a);
3211     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3212
3213     return WINED3D_OK;
3214 }
3215
3216 /*****
3217  * Get / Set Indices
3218  *****/
3219 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3220                                              UINT BaseVertexIndex) {
3221     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
3222     IWineD3DIndexBuffer *oldIdxs;
3223
3224     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3225     oldIdxs = This->updateStateBlock->pIndexData;
3226
3227     This->updateStateBlock->changed.indices = TRUE;
3228     This->updateStateBlock->set.indices = TRUE;
3229     This->updateStateBlock->pIndexData = pIndexData;
3230     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3231
3232     /* Handle recording of state blocks */
3233     if (This->isRecordingState) {
3234         TRACE("Recording... not performing anything\n");
3235         return WINED3D_OK;
3236     }
3237
3238     if (NULL != pIndexData) {
3239         IWineD3DIndexBuffer_AddRef(pIndexData);
3240     }
3241     if (NULL != oldIdxs) {
3242         IWineD3DIndexBuffer_Release(oldIdxs);
3243     }
3244     return WINED3D_OK;
3245 }
3246
3247 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3248     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3249
3250     *ppIndexData = This->stateBlock->pIndexData;
3251
3252     /* up ref count on ppindexdata */
3253     if (*ppIndexData) {
3254         IWineD3DIndexBuffer_AddRef(*ppIndexData);
3255         *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3256         TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3257     }else{
3258         TRACE("(%p) No index data set\n", This);
3259     }
3260     TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3261
3262     return WINED3D_OK;
3263 }
3264
3265 /*****
3266  * Get / Set Viewports
3267  *****/
3268 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3269     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3270
3271     TRACE("(%p)\n", This);
3272     This->updateStateBlock->changed.viewport = TRUE;
3273     This->updateStateBlock->set.viewport = TRUE;
3274     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3275
3276     /* Handle recording of state blocks */
3277     if (This->isRecordingState) {
3278         TRACE("Recording... not performing anything\n");
3279         return WINED3D_OK;
3280     }
3281     This->viewport_changed = TRUE;
3282
3283     ENTER_GL();
3284
3285     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3286           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3287
3288     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3289     checkGLcall("glDepthRange");
3290     /* Note: GL requires lower left, DirectX supplies upper left */
3291     /* TODO: replace usage of renderTarget with context management */
3292     glViewport(pViewport->X,
3293                (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3294                pViewport->Width, pViewport->Height);
3295
3296     checkGLcall("glViewport");
3297
3298     LEAVE_GL();
3299
3300     return WINED3D_OK;
3301
3302 }
3303
3304 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3305     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3306     TRACE("(%p)\n", This);
3307     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3308     return WINED3D_OK;
3309 }
3310
3311 static void renderstate_stencil_twosided(
3312         IWineD3DDeviceImpl *This,
3313         GLint face,
3314         GLint func,
3315         GLint ref,
3316         GLuint mask,
3317         GLint stencilFail,
3318         GLint depthFail,
3319         GLint stencilPass ) {
3320 #if 0 /* Don't use OpenGL 2.0 calls for now */
3321             if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3322                 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3323                 checkGLcall("glStencilFuncSeparate(...)");
3324                 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3325                 checkGLcall("glStencilOpSeparate(...)");
3326             }
3327             else
3328 #endif
3329             if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3330                 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3331                 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3332                 GL_EXTCALL(glActiveStencilFaceEXT(face));
3333                 checkGLcall("glActiveStencilFaceEXT(...)");
3334                 glStencilFunc(func, ref, mask);
3335                 checkGLcall("glStencilFunc(...)");
3336                 glStencilOp(stencilFail, depthFail, stencilPass);
3337                 checkGLcall("glStencilOp(...)");
3338             } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3339                 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3340                 checkGLcall("glStencilFuncSeparateATI(...)");
3341                 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3342                 checkGLcall("glStencilOpSeparateATI(...)");
3343             } else {
3344                 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3345             }
3346 }
3347
3348 static void renderstate_stencil(IWineD3DDeviceImpl *This, WINED3DRENDERSTATETYPE State, DWORD Value) {
3349     DWORD onesided_enable = FALSE;
3350     DWORD twosided_enable = FALSE;
3351     GLint func = GL_ALWAYS;
3352     GLint func_ccw = GL_ALWAYS;
3353     GLint ref = 0;
3354     GLuint mask = 0;
3355     GLint stencilFail = GL_KEEP;
3356     GLint depthFail = GL_KEEP;
3357     GLint stencilPass = GL_KEEP;
3358     GLint stencilFail_ccw = GL_KEEP;
3359     GLint depthFail_ccw = GL_KEEP;
3360     GLint stencilPass_ccw = GL_KEEP;
3361
3362     if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3363         onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3364     if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3365         twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3366     if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3367         if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3368             func = GL_ALWAYS;
3369     if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3370         if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3371             func = GL_ALWAYS;
3372     if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3373         ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3374     if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3375         mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3376     if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3377         stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3378     if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3379         depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3380     if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3381         stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3382     if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3383         stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3384     if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3385         depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3386     if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3387         stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3388
3389     TRACE("(onesided %d, twosided %d, ref %x, mask %x,  \
3390         GL_FRONT: func: %x, fail %x, zfail %x, zpass %x  \
3391         GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3392             onesided_enable, twosided_enable, ref, mask,
3393             func, stencilFail, depthFail, stencilPass,
3394             func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3395
3396     if (twosided_enable) {
3397         renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3398         renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3399     } else {
3400         if (onesided_enable) {
3401             glEnable(GL_STENCIL_TEST);
3402             checkGLcall("glEnable GL_STENCIL_TEST");
3403             glStencilFunc(func, ref, mask);
3404             checkGLcall("glStencilFunc(...)");
3405             glStencilOp(stencilFail, depthFail, stencilPass);
3406             checkGLcall("glStencilOp(...)");
3407         } else {
3408             glDisable(GL_STENCIL_TEST);
3409             checkGLcall("glDisable GL_STENCIL_TEST");
3410         }
3411     }
3412 }
3413
3414 /*****
3415  * Get / Set Render States
3416  * TODO: Verify against dx9 definitions
3417  *****/
3418 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
3419
3420     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
3421
3422     /* Simple way of referring to either a DWORD or a 4 byte float */
3423     union {
3424         DWORD d;
3425         float f;
3426     } tmpvalue;
3427
3428     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3429     This->updateStateBlock->changed.renderState[State] = TRUE;
3430     This->updateStateBlock->set.renderState[State] = TRUE;
3431     This->updateStateBlock->renderState[State] = Value;
3432
3433     /* Handle recording of state blocks */
3434     if (This->isRecordingState) {
3435         TRACE("Recording... not performing anything\n");
3436         return WINED3D_OK;
3437     }
3438
3439     ENTER_GL();
3440
3441     switch (State) {
3442     case WINED3DRS_FILLMODE                  :
3443     case WINED3DRS_LIGHTING                  :
3444     case WINED3DRS_ZENABLE                   :
3445     case WINED3DRS_CULLMODE                  :
3446     case WINED3DRS_SHADEMODE                 :
3447     case WINED3DRS_DITHERENABLE              :
3448     case WINED3DRS_ZWRITEENABLE              :
3449     case WINED3DRS_ZFUNC                     :
3450     case WINED3DRS_AMBIENT                   :
3451     case WINED3DRS_ALPHABLENDENABLE          :
3452     case WINED3DRS_SRCBLEND                  :
3453     case WINED3DRS_DESTBLEND                 :
3454     case WINED3DRS_ANTIALIASEDLINEENABLE     :
3455     case WINED3DRS_BLENDFACTOR               :
3456     case WINED3DRS_ALPHATESTENABLE           :
3457     case WINED3DRS_ALPHAFUNC                 :
3458     case WINED3DRS_ALPHAREF                  :
3459     case WINED3DRS_COLORKEYENABLE            :
3460     case WINED3DRS_CLIPPLANEENABLE           :
3461     case WINED3DRS_CLIPPING                  :
3462     case WINED3DRS_BLENDOP                   :
3463         StateTable[STATE_RENDER(State)].apply(STATE_RENDER(State), This->stateBlock);
3464         break;
3465
3466     case WINED3DRS_TEXTUREFACTOR             :
3467         {
3468             unsigned int i;
3469
3470             /* Note the texture color applies to all textures whereas
3471                GL_TEXTURE_ENV_COLOR applies to active only */
3472             float col[4];
3473             D3DCOLORTOGLFLOAT4(Value, col);
3474
3475             if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3476                 /* And now the default texture color as well */
3477                 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3478                     /* Note the WINED3DRS value applies to all textures, but GL has one
3479                        per texture, so apply it now ready to be used!               */
3480                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3481                         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3482                         checkGLcall("glActiveTextureARB");
3483                     } else if (i>0) {
3484                         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3485                     }
3486
3487                     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3488                     checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3489                 }
3490             }
3491         }
3492         break;
3493
3494     case WINED3DRS_SPECULARENABLE            :
3495         {
3496             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3497                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3498                specular color. This is wrong:
3499                Separate specular color means the specular colour is maintained separately, whereas
3500                single color means it is merged in. However in both cases they are being used to
3501                some extent.
3502                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3503                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3504                   running 1.4 yet!
3505              */
3506             /*
3507              * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3508              * Instead, we need to setup the FinalCombiner properly.
3509              *
3510              * The default setup for the FinalCombiner is:
3511              *
3512              * <variable>       <input>                             <mapping>               <usage>
3513              * GL_VARIABLE_A_NV GL_FOG,                             GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3514              * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV   GL_UNSIGNED_IDENTITY_NV GL_RGB
3515              * GL_VARIABLE_C_NV GL_FOG                              GL_UNSIGNED_IDENTITY_NV GL_RGB
3516              * GL_VARIABLE_D_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
3517              * GL_VARIABLE_E_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
3518              * GL_VARIABLE_F_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
3519              * GL_VARIABLE_G_NV GL_SPARE0_NV                        GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3520              *
3521              * That's pretty much fine as it is, except for variable B, which needs to take
3522              * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3523              * whether WINED3DRS_SPECULARENABLE is enabled or not.
3524              */
3525
3526               if (Value) {
3527                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3528                 checkGLcall("glMaterialfv");
3529                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3530                   glEnable(GL_COLOR_SUM_EXT);
3531                 } else {
3532                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
3533                 }
3534                 checkGLcall("glEnable(GL_COLOR_SUM)");
3535
3536                 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3537                     GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3538                     checkGLcall("glFinalCombinerInputNV()");
3539                 }
3540               } else {
3541                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3542
3543                 /* for the case of enabled lighting: */
3544                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3545                 checkGLcall("glMaterialfv");
3546
3547                 /* for the case of disabled lighting: */
3548                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3549                   glDisable(GL_COLOR_SUM_EXT);
3550                 } else {
3551                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
3552                 }
3553                 checkGLcall("glDisable(GL_COLOR_SUM)");
3554
3555                 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3556                     GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3557                     checkGLcall("glFinalCombinerInputNV()");
3558                 }
3559               }
3560         }
3561         break;
3562
3563     case WINED3DRS_STENCILENABLE :
3564     case WINED3DRS_TWOSIDEDSTENCILMODE :
3565     case WINED3DRS_STENCILFUNC :
3566     case WINED3DRS_CCW_STENCILFUNC :
3567     case WINED3DRS_STENCILREF :
3568     case WINED3DRS_STENCILMASK :
3569     case WINED3DRS_STENCILFAIL :
3570     case WINED3DRS_STENCILZFAIL :
3571     case WINED3DRS_STENCILPASS :
3572     case WINED3DRS_CCW_STENCILFAIL :
3573     case WINED3DRS_CCW_STENCILZFAIL :
3574     case WINED3DRS_CCW_STENCILPASS :
3575     case WINED3DRS_EDGEANTIALIAS             :
3576         renderstate_stencil(This, State, Value);
3577         break;
3578     case WINED3DRS_STENCILWRITEMASK          :
3579         {
3580             glStencilMask(Value);
3581             TRACE("glStencilMask(%u)\n", Value);
3582             checkGLcall("glStencilMask");
3583         }
3584         break;
3585
3586     case WINED3DRS_FOGENABLE                 :
3587         {
3588           if (Value) {
3589                glEnable(GL_FOG);
3590                checkGLcall("glEnable GL_FOG");
3591             } else {
3592                glDisable(GL_FOG);
3593                checkGLcall("glDisable GL_FOG");
3594             }
3595         }
3596         break;
3597
3598     case WINED3DRS_RANGEFOGENABLE            :
3599         {
3600             if (Value) {
3601               TRACE("Enabled RANGEFOG\n");
3602             } else {
3603               TRACE("Disabled RANGEFOG\n");
3604             }
3605         }
3606         break;
3607
3608     case WINED3DRS_FOGCOLOR                  :
3609         {
3610             float col[4];
3611             D3DCOLORTOGLFLOAT4(Value, col);
3612             /* Set the default alpha blend color */
3613             glFogfv(GL_FOG_COLOR, &col[0]);
3614             checkGLcall("glFog GL_FOG_COLOR");
3615         }
3616         break;
3617
3618     case WINED3DRS_FOGTABLEMODE              :
3619     case WINED3DRS_FOGVERTEXMODE             :
3620         {
3621           /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes, the system will apply only pixel(=table) fog effects." */
3622           if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
3623               glHint(GL_FOG_HINT, GL_FASTEST);
3624               checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3625               switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3626                   /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3627                    * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3628                    */
3629                   case WINED3DFOG_EXP:  {
3630                       if(!This->last_was_rhw) {
3631                           glFogi(GL_FOG_MODE, GL_EXP);
3632                           checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3633                           if(GL_SUPPORT(EXT_FOG_COORD)) {
3634                               glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3635                               checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3636                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3637                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3638                           }
3639                           break;
3640                       }
3641                   }
3642                   case WINED3DFOG_EXP2: {
3643                       if(!This->last_was_rhw) {
3644                           glFogi(GL_FOG_MODE, GL_EXP2);
3645                           checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3646                           if(GL_SUPPORT(EXT_FOG_COORD)) {
3647                               glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3648                               checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3649                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3650                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3651                           }
3652                           break;
3653                       }
3654                   }
3655                   case WINED3DFOG_LINEAR: {
3656                       if(!This->last_was_rhw) {
3657                           glFogi(GL_FOG_MODE, GL_LINEAR);
3658                           checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3659                           if(GL_SUPPORT(EXT_FOG_COORD)) {
3660                               glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3661                               checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3662                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3663                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3664                           }
3665                           break;
3666                       }
3667                   }
3668                   case WINED3DFOG_NONE: {
3669                       /* Both are none? According to msdn the alpha channel of the specular
3670                        * color contains a fog factor. Set it in drawStridedSlow.
3671                        * Same happens with Vertexfog on transformed vertices
3672                        */
3673                       if(GL_SUPPORT(EXT_FOG_COORD)) {
3674                           glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3675                           checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3676                           glFogi(GL_FOG_MODE, GL_LINEAR);
3677                           checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3678                           glFogf(GL_FOG_START, (float) 0xff);
3679                           checkGLcall("glFogfv GL_FOG_START");
3680                           glFogf(GL_FOG_END, 0.0);
3681                           checkGLcall("glFogfv GL_FOG_END");
3682                       } else {
3683                           /* Disable GL fog, handle this in software in drawStridedSlow */
3684                           glDisable(GL_FOG);
3685                           checkGLcall("glDisable(GL_FOG)");
3686                       }
3687                   break;
3688                   }
3689                   default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3690               }
3691           } else {
3692               glHint(GL_FOG_HINT, GL_NICEST);
3693               checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3694               switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3695                   case WINED3DFOG_EXP:
3696                                       glFogi(GL_FOG_MODE, GL_EXP);
3697                                       checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3698                                       if(GL_SUPPORT(EXT_FOG_COORD)) {
3699                                           glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3700                                           checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3701                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3702                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3703                                       }
3704                                       break;
3705                   case WINED3DFOG_EXP2:
3706                                       glFogi(GL_FOG_MODE, GL_EXP2);
3707                                       checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3708                                       if(GL_SUPPORT(EXT_FOG_COORD)) {
3709                                           glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3710                                           checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3711                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3712                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3713                                       }
3714                                       break;
3715                   case WINED3DFOG_LINEAR:
3716                                       glFogi(GL_FOG_MODE, GL_LINEAR);
3717                                       checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3718                                       if(GL_SUPPORT(EXT_FOG_COORD)) {
3719                                           glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3720                                           checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3721                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3722                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3723                                       }
3724                                       break;
3725                   case WINED3DFOG_NONE:
3726                   default:            /* Won't happen */
3727                                       FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
3728               }
3729           }
3730           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3731             glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3732           }
3733         }
3734         break;
3735
3736     case WINED3DRS_FOGSTART                  :
3737         {
3738             tmpvalue.d = Value;
3739             glFogfv(GL_FOG_START, &tmpvalue.f);
3740             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3741             TRACE("Fog Start == %f\n", tmpvalue.f);
3742         }
3743         break;
3744
3745     case WINED3DRS_FOGEND                    :
3746         {
3747             tmpvalue.d = Value;
3748             glFogfv(GL_FOG_END, &tmpvalue.f);
3749             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3750             TRACE("Fog End == %f\n", tmpvalue.f);
3751         }
3752         break;
3753
3754     case WINED3DRS_FOGDENSITY                :
3755         {
3756             tmpvalue.d = Value;
3757             glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3758             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3759         }
3760         break;
3761
3762     case WINED3DRS_VERTEXBLEND               :
3763         {
3764           This->updateStateBlock->vertex_blend = (WINED3DVERTEXBLENDFLAGS) Value;
3765           TRACE("Vertex Blending state to %d\n",  Value);
3766         }
3767         break;
3768
3769     case WINED3DRS_TWEENFACTOR               :
3770         {
3771           tmpvalue.d = Value;
3772           This->updateStateBlock->tween_factor = tmpvalue.f;
3773           TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3774         }
3775         break;
3776
3777     case WINED3DRS_INDEXEDVERTEXBLENDENABLE  :
3778         {
3779           TRACE("Indexed Vertex Blend Enable to %u\n", (BOOL) Value);
3780         }
3781         break;
3782
3783     case WINED3DRS_COLORVERTEX               :
3784     case WINED3DRS_DIFFUSEMATERIALSOURCE     :
3785     case WINED3DRS_SPECULARMATERIALSOURCE    :
3786     case WINED3DRS_AMBIENTMATERIALSOURCE     :
3787     case WINED3DRS_EMISSIVEMATERIALSOURCE    :
3788         {
3789             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3790
3791             if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3792                 TRACE("diff %d, amb %d, emis %d, spec %d\n",
3793                       This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3794                       This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3795                       This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3796                       This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3797
3798                 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
3799                     if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
3800                         Parm = GL_AMBIENT_AND_DIFFUSE;
3801                     } else {
3802                         Parm = GL_DIFFUSE;
3803                     }
3804                 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
3805                     Parm = GL_AMBIENT;
3806                 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
3807                     Parm = GL_EMISSION;
3808                 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
3809                     Parm = GL_SPECULAR;
3810                 } else {
3811                     Parm = -1;
3812                 }
3813
3814                 if (Parm == -1) {
3815                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3816                 } else {
3817                     This->tracking_color = NEEDS_TRACKING;
3818                     This->tracking_parm  = Parm;
3819                 }
3820
3821             } else {
3822                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3823             }
3824         }
3825         break;
3826
3827     case WINED3DRS_LINEPATTERN               :
3828         {
3829             union {
3830                 DWORD                 d;
3831                 WINED3DLINEPATTERN    lp;
3832             } tmppattern;
3833             tmppattern.d = Value;
3834
3835             TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3836
3837             if (tmppattern.lp.wRepeatFactor) {
3838                 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3839                 checkGLcall("glLineStipple(repeat, linepattern)");
3840                 glEnable(GL_LINE_STIPPLE);
3841                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3842             } else {
3843                 glDisable(GL_LINE_STIPPLE);
3844                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3845             }
3846         }
3847         break;
3848
3849     case WINED3DRS_ZBIAS                     : /* D3D8 only */
3850         {
3851             if (Value) {
3852                 tmpvalue.d = Value;
3853                 TRACE("ZBias value %f\n", tmpvalue.f);
3854                 glPolygonOffset(0, -tmpvalue.f);
3855                 checkGLcall("glPolygonOffset(0, -Value)");
3856                 glEnable(GL_POLYGON_OFFSET_FILL);
3857                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3858                 glEnable(GL_POLYGON_OFFSET_LINE);
3859                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3860                 glEnable(GL_POLYGON_OFFSET_POINT);
3861                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3862             } else {
3863                 glDisable(GL_POLYGON_OFFSET_FILL);
3864                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3865                 glDisable(GL_POLYGON_OFFSET_LINE);
3866                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3867                 glDisable(GL_POLYGON_OFFSET_POINT);
3868                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3869             }
3870         }
3871         break;
3872
3873     case WINED3DRS_NORMALIZENORMALS          :
3874         if (Value) {
3875             glEnable(GL_NORMALIZE);
3876             checkGLcall("glEnable(GL_NORMALIZE);");
3877         } else {
3878             glDisable(GL_NORMALIZE);
3879             checkGLcall("glDisable(GL_NORMALIZE);");
3880         }
3881         break;
3882
3883     case WINED3DRS_POINTSIZE                 :
3884         /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3885         tmpvalue.d = Value;
3886         TRACE("Set point size to %f\n", tmpvalue.f);
3887         glPointSize(tmpvalue.f);
3888         checkGLcall("glPointSize(...);");
3889         break;
3890
3891     case WINED3DRS_POINTSIZE_MIN             :
3892         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3893           tmpvalue.d = Value;
3894           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3895           checkGLcall("glPointParameterfEXT(...);");
3896         } else {
3897           FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3898         }
3899         break;
3900
3901     case WINED3DRS_POINTSIZE_MAX             :
3902         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3903           tmpvalue.d = Value;
3904           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3905           checkGLcall("glPointParameterfEXT(...);");
3906         } else {
3907           FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3908         }
3909         break;
3910
3911     case WINED3DRS_POINTSCALE_A              :
3912     case WINED3DRS_POINTSCALE_B              :
3913     case WINED3DRS_POINTSCALE_C              :
3914     case WINED3DRS_POINTSCALEENABLE          :
3915     {
3916         /*
3917          * POINTSCALEENABLE controls how point size value is treated. If set to
3918          * true, the point size is scaled with respect to height of viewport.
3919          * When set to false point size is in pixels.
3920          *
3921          * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3922          */
3923
3924         /* Default values */
3925         GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3926
3927         /*
3928          * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3929          * This means that OpenGL will clamp really small point sizes to 1.0f.
3930          * To correct for this we need to multiply by the scale factor when sizes
3931          * are less than 1.0f. scale_factor =  1.0f / point_size.
3932          */
3933         GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
3934         if(pointSize > 0.0f) {
3935             GLfloat scaleFactor;
3936
3937             if(pointSize < 1.0f) {
3938                 scaleFactor = pointSize * pointSize;
3939             } else {
3940                 scaleFactor = 1.0f;
3941             }
3942
3943             if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3944                 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
3945                     (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3946                 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
3947                     (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3948                 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
3949                     (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
3950             }
3951         }
3952
3953         if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3954             GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3955             checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3956         }
3957         else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3958             GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3959             checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3960         } else {
3961             TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3962         }
3963         break;
3964     }
3965     case WINED3DRS_COLORWRITEENABLE          :
3966       {
3967         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3968               Value & WINED3DCOLORWRITEENABLE_RED   ? 1 : 0,
3969               Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3970               Value & WINED3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
3971               Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3972         glColorMask(Value & WINED3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE,
3973                     Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3974                     Value & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
3975                     Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3976         checkGLcall("glColorMask(...)");
3977       }
3978       break;
3979
3980     case WINED3DRS_LOCALVIEWER               :
3981       {
3982         GLint state = (Value) ? 1 : 0;
3983         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3984         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3985       }
3986       break;
3987
3988     case WINED3DRS_LASTPIXEL                 :
3989       {
3990         if (Value) {
3991           TRACE("Last Pixel Drawing Enabled\n");
3992         } else {
3993           FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3994         }
3995       }
3996       break;
3997
3998     case WINED3DRS_SOFTWAREVERTEXPROCESSING  :
3999       {
4000         if (Value) {
4001           TRACE("Software Processing Enabled\n");
4002         } else {
4003           TRACE("Software Processing Disabled\n");
4004         }
4005       }
4006       break;
4007
4008       /** not supported */
4009     case WINED3DRS_ZVISIBLE                  :
4010       {
4011         LEAVE_GL();
4012         return WINED3DERR_INVALIDCALL;
4013       }
4014     case WINED3DRS_POINTSPRITEENABLE         :
4015     {
4016         /* TODO: NV_POINT_SPRITE */
4017         if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4018             TRACE("Point sprites not supported\n");
4019             break;
4020         }
4021
4022         /*
4023          * Point sprites are always enabled. Value controls texture coordinate
4024          * replacement mode. Must be set true for point sprites to use
4025          * textures.
4026          */
4027         glEnable(GL_POINT_SPRITE_ARB);
4028         checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4029
4030         if (Value) {
4031             glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4032             checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4033         } else {
4034             glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4035             checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4036         }
4037         break;
4038     }
4039
4040     case WINED3DRS_WRAP0                     :
4041     case WINED3DRS_WRAP1                     :
4042     case WINED3DRS_WRAP2                     :
4043     case WINED3DRS_WRAP3                     :
4044     case WINED3DRS_WRAP4                     :
4045     case WINED3DRS_WRAP5                     :
4046     case WINED3DRS_WRAP6                     :
4047     case WINED3DRS_WRAP7                     :
4048     case WINED3DRS_WRAP8                     :
4049     case WINED3DRS_WRAP9                     :
4050     case WINED3DRS_WRAP10                    :
4051     case WINED3DRS_WRAP11                    :
4052     case WINED3DRS_WRAP12                    :
4053     case WINED3DRS_WRAP13                    :
4054     case WINED3DRS_WRAP14                    :
4055     case WINED3DRS_WRAP15                    :
4056     /**
4057     http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4058     http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4059     http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4060     Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4061     http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4062
4063     so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4064     */
4065     {
4066         if(Value) {
4067             ERR("(%p)->(%s,%d) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4068         }
4069         break;
4070     }
4071
4072     case WINED3DRS_MULTISAMPLEANTIALIAS      :
4073     {
4074         if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4075             if(Value) {
4076                 glEnable(GL_MULTISAMPLE_ARB);
4077                 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4078             } else {
4079                 glDisable(GL_MULTISAMPLE_ARB);
4080                 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4081             }
4082         } else {
4083             if(Value) {
4084                 ERR("Multisample antialiasing not supported by gl\n");
4085             }
4086         }
4087         break;
4088     }
4089
4090     case WINED3DRS_SCISSORTESTENABLE :
4091     {
4092         if(Value) {
4093             glEnable(GL_SCISSOR_TEST);
4094             checkGLcall("glEnable(GL_SCISSOR_TEST)");
4095         } else {
4096             glDisable(GL_SCISSOR_TEST);
4097             checkGLcall("glDisable(GL_SCISSOR_TEST)");
4098         }
4099         break;
4100     }
4101     case WINED3DRS_SLOPESCALEDEPTHBIAS :
4102     {
4103         if(Value) {
4104             tmpvalue.d = Value;
4105             glEnable(GL_POLYGON_OFFSET_FILL);
4106             checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4107             glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4108             checkGLcall("glPolygonOffset(...)");
4109         } else {
4110             glDisable(GL_POLYGON_OFFSET_FILL);
4111             checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4112         }
4113         break;
4114     }
4115     {
4116         if(Value) {
4117             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4118             glEnable(GL_BLEND);
4119             checkGLcall("glEnable(GL_BLEND)");
4120             glEnable(GL_LINE_SMOOTH);
4121             checkGLcall("glEnable(GL_LINE_SMOOTH)");
4122         } else {
4123             glDisable(GL_BLEND);
4124             checkGLcall("glDisable(GL_BLEND)");
4125             glDisable(GL_LINE_SMOOTH);
4126             checkGLcall("glDisable(GL_LINE_SMOOTH)");
4127         }
4128         break;
4129     }
4130
4131     case WINED3DRS_DEPTHBIAS :
4132     {
4133         if(Value) {
4134             tmpvalue.d = Value;
4135             glEnable(GL_POLYGON_OFFSET_FILL);
4136             checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4137             glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4138             checkGLcall("glPolygonOffset(...)");
4139         } else {
4140             glDisable(GL_POLYGON_OFFSET_FILL);
4141             checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4142         }
4143         break;
4144     }
4145
4146     case WINED3DRS_TEXTUREPERSPECTIVE    :
4147     {
4148         if (Value)
4149             glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4150         else
4151             glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4152         break;
4153     }
4154
4155     case WINED3DRS_STIPPLEDALPHA    :
4156     {
4157         if (Value)
4158             ERR(" Stippled Alpha not supported yet.\n");
4159         break;
4160     }
4161     case WINED3DRS_ANTIALIAS :
4162     {
4163         if (Value)
4164             ERR(" Antialias not supported yet.\n");
4165         break;
4166     }
4167
4168     case WINED3DRS_MULTISAMPLEMASK :
4169     {
4170         if(0xFFFFFFFF != Value)
4171             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4172         break;
4173     }
4174
4175     case WINED3DRS_PATCHEDGESTYLE :
4176     {
4177         if(WINED3DPATCHEDGE_DISCRETE != Value)
4178             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4179         break;
4180     }
4181
4182     case WINED3DRS_PATCHSEGMENTS :
4183     {
4184         /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4185         tmpvalue.f = 1.0f;
4186         if(tmpvalue.d != Value)
4187             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4188         break;
4189     }
4190
4191     case WINED3DRS_DEBUGMONITORTOKEN :
4192     {
4193         /* Only useful for "debug builds". */
4194         if(0xbaadcafe != Value) {
4195             /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4196             /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4197              * but our tests disagree.
4198              * We do not claim to implement a debugging lib, so do not write an ERR
4199              */
4200             WARN("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4201         }
4202         break;
4203     }
4204
4205     case WINED3DRS_POSITIONDEGREE :
4206     {
4207         if(WINED3DDEGREE_CUBIC != Value)
4208             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4209         break;
4210     }
4211
4212     case WINED3DRS_NORMALDEGREE :
4213     {
4214         if(WINED3DDEGREE_LINEAR != Value)
4215             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4216         break;
4217     }
4218
4219     case WINED3DRS_MINTESSELLATIONLEVEL :
4220     case WINED3DRS_MAXTESSELLATIONLEVEL :
4221     case WINED3DRS_ADAPTIVETESS_X :
4222     case WINED3DRS_ADAPTIVETESS_Y :
4223     case WINED3DRS_ADAPTIVETESS_Z :
4224     case WINED3DRS_ADAPTIVETESS_W :
4225     {
4226         if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4227             FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4228         else
4229             TRACE("(%p)->(%s,%d): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4230         break;
4231     }
4232
4233     case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4234     {
4235         if(Value)
4236             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4237         break;
4238     }
4239
4240     case WINED3DRS_COLORWRITEENABLE1         :
4241     case WINED3DRS_COLORWRITEENABLE2         :
4242     case WINED3DRS_COLORWRITEENABLE3         :
4243     {
4244         /* depends on WINED3DRS_COLORWRITEENABLE. */
4245         if(0x0000000F != Value)
4246             ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4247         break;
4248     }
4249
4250     case WINED3DRS_SRGBWRITEENABLE           :
4251     {
4252         if(Value)
4253             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4254         break;
4255     }
4256
4257     case WINED3DRS_SEPARATEALPHABLENDENABLE  :
4258     {
4259         if(Value)
4260             ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4261         break;
4262     }
4263
4264     case WINED3DRS_SRCBLENDALPHA             :
4265     case WINED3DRS_DESTBLENDALPHA            :
4266     case WINED3DRS_BLENDOPALPHA              :
4267     {
4268         if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4269             FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4270         else
4271             TRACE("(%p)->(%s,%d): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4272         break;
4273     }
4274
4275     default:
4276         FIXME("(%p)->(%s,%d) unknown state\n", This, debug_d3drenderstate(State), Value);
4277     }
4278
4279     LEAVE_GL();
4280
4281     return WINED3D_OK;
4282 }
4283
4284 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
4285     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4286     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
4287     *pValue = This->stateBlock->renderState[State];
4288     return WINED3D_OK;
4289 }
4290
4291 /*****
4292  * Get / Set Sampler States
4293  * TODO: Verify against dx9 definitions
4294  *****/
4295
4296 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4297     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4298     /**
4299     * SetSampler is designed to allow for more than the standard up to 8 textures
4300     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
4301     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4302     *
4303     * http://developer.nvidia.com/object/General_FAQ.html#t6
4304     *
4305     * There are two new settings for GForce
4306     * the sampler one:
4307     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4308     * and the texture one:
4309     * GL_MAX_TEXTURE_COORDS_ARB.
4310     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4311      ******************/
4312     /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4313     if(Sampler >  GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4314          FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4315             Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4316         return WINED3DERR_INVALIDCALL;
4317     }
4318
4319     TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
4320         debug_d3dsamplerstate(Type), Type, Value);
4321     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
4322     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
4323     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4324
4325     /* Handle recording of state blocks */
4326     if (This->isRecordingState) {
4327         TRACE("Recording... not performing anything\n");
4328         return WINED3D_OK;
4329     }
4330
4331     return WINED3D_OK;
4332 }
4333
4334 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4335     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4336     /** TODO: check that sampler is in  range **/
4337     *Value = This->stateBlock->samplerState[Sampler][Type];
4338     TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
4339
4340     return WINED3D_OK;
4341 }
4342
4343 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4344     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4345     RECT windowRect;
4346     UINT winHeight;
4347
4348     GetClientRect(((IWineD3DSwapChainImpl *)This->swapchains[0])->win_handle, &windowRect);
4349     /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4350     * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4351     */
4352     winHeight = windowRect.bottom - windowRect.top;
4353     TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->bottom - winHeight,
4354           pRect->right - pRect->left, pRect->bottom - pRect->top);
4355     ENTER_GL();
4356     glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4357     checkGLcall("glScissor");
4358     LEAVE_GL();
4359
4360     return WINED3D_OK;
4361 }
4362
4363 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4364     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4365     GLint scissorBox[4];
4366
4367     ENTER_GL();
4368     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4369     glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4370     pRect->left = scissorBox[0];
4371     pRect->top = scissorBox[1];
4372     pRect->right = scissorBox[0] + scissorBox[2];
4373     pRect->bottom = scissorBox[1] + scissorBox[3];
4374     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4375     LEAVE_GL();
4376     return WINED3D_OK;
4377 }
4378
4379 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4380     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4381     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4382
4383     TRACE("(%p) : pDecl=%p\n", This, pDecl);
4384
4385     This->updateStateBlock->vertexDecl = pDecl;
4386     This->updateStateBlock->changed.vertexDecl = TRUE;
4387     This->updateStateBlock->set.vertexDecl = TRUE;
4388
4389     if (This->isRecordingState) {
4390         TRACE("Recording... not performing anything\n");
4391     }
4392
4393     if (NULL != pDecl) {
4394         IWineD3DVertexDeclaration_AddRef(pDecl);
4395     }
4396     if (NULL != oldDecl) {
4397         IWineD3DVertexDeclaration_Release(oldDecl);
4398     }
4399     return WINED3D_OK;
4400 }
4401
4402 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4403     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4404
4405     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4406
4407     *ppDecl = This->stateBlock->vertexDecl;
4408     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4409     return WINED3D_OK;
4410 }
4411
4412 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4413     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
4414     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4415
4416     This->updateStateBlock->vertexShader         = pShader;
4417     This->updateStateBlock->changed.vertexShader = TRUE;
4418     This->updateStateBlock->set.vertexShader     = TRUE;
4419
4420     if (This->isRecordingState) {
4421         TRACE("Recording... not performing anything\n");
4422     }
4423
4424     if (NULL != pShader) {
4425         IWineD3DVertexShader_AddRef(pShader);
4426     }
4427     if (NULL != oldShader) {
4428         IWineD3DVertexShader_Release(oldShader);
4429     }
4430
4431     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4432     /**
4433      * TODO: merge HAL shaders context switching from prototype
4434      */
4435     return WINED3D_OK;
4436 }
4437
4438 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4439     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4440
4441     if (NULL == ppShader) {
4442         return WINED3DERR_INVALIDCALL;
4443     }
4444     *ppShader = This->stateBlock->vertexShader;
4445     if( NULL != *ppShader)
4446         IWineD3DVertexShader_AddRef(*ppShader);
4447
4448     TRACE("(%p) : returning %p\n", This, *ppShader);
4449     return WINED3D_OK;
4450 }
4451
4452 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4453     IWineD3DDevice *iface,
4454     UINT start,
4455     CONST BOOL *srcData,
4456     UINT count) {
4457
4458     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4459     int i, cnt = min(count, MAX_CONST_B - start);
4460
4461     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4462             iface, srcData, start, count);
4463
4464     if (srcData == NULL || cnt < 0)
4465         return WINED3DERR_INVALIDCALL;
4466
4467     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4468     for (i = 0; i < cnt; i++)
4469         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4470
4471     for (i = start; i < cnt + start; ++i) {
4472         This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4473         This->updateStateBlock->set.vertexShaderConstantsB[i]     = TRUE;
4474     }
4475
4476     return WINED3D_OK;
4477 }
4478
4479 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4480     IWineD3DDevice *iface,
4481     UINT start,
4482     BOOL *dstData,
4483     UINT count) {
4484
4485     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4486     int cnt = min(count, MAX_CONST_B - start);
4487
4488     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4489             iface, dstData, start, count);
4490
4491     if (dstData == NULL || cnt < 0)
4492         return WINED3DERR_INVALIDCALL;
4493
4494     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4495     return WINED3D_OK;
4496 }
4497
4498 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4499     IWineD3DDevice *iface,
4500     UINT start,
4501     CONST int *srcData,
4502     UINT count) {
4503
4504     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4505     int i, cnt = min(count, MAX_CONST_I - start);
4506
4507     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4508             iface, srcData, start, count);
4509
4510     if (srcData == NULL || cnt < 0)
4511         return WINED3DERR_INVALIDCALL;
4512
4513     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4514     for (i = 0; i < cnt; i++)
4515         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4516            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4517
4518     for (i = start; i < cnt + start; ++i) {
4519         This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4520         This->updateStateBlock->set.vertexShaderConstantsI[i]     = TRUE;
4521     }
4522
4523     return WINED3D_OK;
4524 }
4525
4526 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4527     IWineD3DDevice *iface,
4528     UINT start,
4529     int *dstData,
4530     UINT count) {
4531
4532     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4533     int cnt = min(count, MAX_CONST_I - start);
4534
4535     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4536             iface, dstData, start, count);
4537
4538     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4539         return WINED3DERR_INVALIDCALL;
4540
4541     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4542     return WINED3D_OK;
4543 }
4544
4545 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4546     IWineD3DDevice *iface,
4547     UINT start,
4548     CONST float *srcData,
4549     UINT count) {
4550
4551     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4552     int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4553
4554     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4555             iface, srcData, start, count);
4556
4557     if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4558         return WINED3DERR_INVALIDCALL;
4559
4560     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4561     for (i = 0; i < cnt; i++)
4562         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4563            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4564
4565     for (i = start; i < cnt + start; ++i) {
4566         if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4567             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4568             ptr->idx = i;
4569             list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4570             This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4571         }
4572         This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4573     }
4574
4575     return WINED3D_OK;
4576 }
4577
4578 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4579     IWineD3DDevice *iface,
4580     UINT start,
4581     float *dstData,
4582     UINT count) {
4583
4584     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4585     int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4586
4587     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4588             iface, dstData, start, count);
4589
4590     if (dstData == NULL || cnt < 0)
4591         return WINED3DERR_INVALIDCALL;
4592
4593     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4594     return WINED3D_OK;
4595 }
4596
4597 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4598     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
4599     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
4600     This->updateStateBlock->pixelShader         = pShader;
4601     This->updateStateBlock->changed.pixelShader = TRUE;
4602     This->updateStateBlock->set.pixelShader     = TRUE;
4603
4604     /* Handle recording of state blocks */
4605     if (This->isRecordingState) {
4606         TRACE("Recording... not performing anything\n");
4607     }
4608
4609     if (NULL != pShader) {
4610         IWineD3DPixelShader_AddRef(pShader);
4611     }
4612     if (NULL != oldShader) {
4613         IWineD3DPixelShader_Release(oldShader);
4614     }
4615
4616     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4617     /**
4618      * TODO: merge HAL shaders context switching from prototype
4619      */
4620     return WINED3D_OK;
4621 }
4622
4623 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4624     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4625
4626     if (NULL == ppShader) {
4627         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4628         return WINED3DERR_INVALIDCALL;
4629     }
4630
4631     *ppShader =  This->stateBlock->pixelShader;
4632     if (NULL != *ppShader) {
4633         IWineD3DPixelShader_AddRef(*ppShader);
4634     }
4635     TRACE("(%p) : returning %p\n", This, *ppShader);
4636     return WINED3D_OK;
4637 }
4638
4639 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4640     IWineD3DDevice *iface,
4641     UINT start,
4642     CONST BOOL *srcData,
4643     UINT count) {
4644
4645     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4646     int i, cnt = min(count, MAX_CONST_B - start);
4647
4648     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4649             iface, srcData, start, count);
4650
4651     if (srcData == NULL || cnt < 0)
4652         return WINED3DERR_INVALIDCALL;
4653
4654     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4655     for (i = 0; i < cnt; i++)
4656         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4657
4658     for (i = start; i < cnt + start; ++i) {
4659         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4660         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
4661     }
4662
4663     return WINED3D_OK;
4664 }
4665
4666 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4667     IWineD3DDevice *iface,
4668     UINT start,
4669     BOOL *dstData,
4670     UINT count) {
4671
4672     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4673     int cnt = min(count, MAX_CONST_B - start);
4674
4675     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4676             iface, dstData, start, count);
4677
4678     if (dstData == NULL || cnt < 0)
4679         return WINED3DERR_INVALIDCALL;
4680
4681     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4682     return WINED3D_OK;
4683 }
4684
4685 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4686     IWineD3DDevice *iface,
4687     UINT start,
4688     CONST int *srcData,
4689     UINT count) {
4690
4691     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4692     int i, cnt = min(count, MAX_CONST_I - start);
4693
4694     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4695             iface, srcData, start, count);
4696
4697     if (srcData == NULL || cnt < 0)
4698         return WINED3DERR_INVALIDCALL;
4699
4700     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4701     for (i = 0; i < cnt; i++)
4702         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4703            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4704
4705     for (i = start; i < cnt + start; ++i) {
4706         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
4707         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
4708     }
4709
4710     return WINED3D_OK;
4711 }
4712
4713 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
4714     IWineD3DDevice *iface,
4715     UINT start,
4716     int *dstData,
4717     UINT count) {
4718
4719     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4720     int cnt = min(count, MAX_CONST_I - start);
4721
4722     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4723             iface, dstData, start, count);
4724
4725     if (dstData == NULL || cnt < 0)
4726         return WINED3DERR_INVALIDCALL;
4727
4728     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4729     return WINED3D_OK;
4730 }
4731
4732 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
4733     IWineD3DDevice *iface,
4734     UINT start,
4735     CONST float *srcData,
4736     UINT count) {
4737
4738     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4739     int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
4740
4741     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4742             iface, srcData, start, count);
4743
4744     if (srcData == NULL || cnt < 0)
4745         return WINED3DERR_INVALIDCALL;
4746
4747     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4748     for (i = 0; i < cnt; i++)
4749         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4750            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4751
4752     for (i = start; i < cnt + start; ++i) {
4753         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
4754             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4755             ptr->idx = i;
4756             list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
4757             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
4758         }
4759         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
4760     }
4761
4762     return WINED3D_OK;
4763 }
4764
4765 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
4766     IWineD3DDevice *iface,
4767     UINT start,
4768     float *dstData,
4769     UINT count) {
4770
4771     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4772     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
4773
4774     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4775             iface, dstData, start, count);
4776
4777     if (dstData == NULL || cnt < 0)
4778         return WINED3DERR_INVALIDCALL;
4779
4780     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4781     return WINED3D_OK;
4782 }
4783
4784 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4785 static HRESULT
4786 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
4787     char *dest_ptr, *dest_conv = NULL;
4788     unsigned int i;
4789     DWORD DestFVF = dest->fvf;
4790     WINED3DVIEWPORT vp;
4791     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
4792     BOOL doClip;
4793     int numTextures;
4794
4795     if (SrcFVF & WINED3DFVF_NORMAL) {
4796         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4797     }
4798
4799     if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
4800         ERR("Source has no position mask\n");
4801         return WINED3DERR_INVALIDCALL;
4802     }
4803
4804     /* We might access VBOs from this code, so hold the lock */
4805     ENTER_GL();
4806
4807     if (dest->resource.allocatedMemory == NULL) {
4808         /* This may happen if we do direct locking into a vbo. Unlikely,
4809          * but theoretically possible(ddraw processvertices test)
4810          */
4811         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
4812         if(!dest->resource.allocatedMemory) {
4813             LEAVE_GL();
4814             ERR("Out of memory\n");
4815             return E_OUTOFMEMORY;
4816         }
4817         if(dest->vbo) {
4818             void *src;
4819             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
4820             checkGLcall("glBindBufferARB");
4821             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
4822             if(src) {
4823                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
4824             }
4825             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4826             checkGLcall("glUnmapBufferARB");
4827         }
4828     }
4829
4830     /* Get a pointer into the destination vbo(create one if none exists) and
4831      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
4832      */
4833     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
4834         CreateVBO(dest);
4835     }
4836
4837     if(dest->vbo) {
4838         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
4839         dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
4840         if(!dest_conv) {
4841             ERR("glMapBuffer failed\n");
4842             /* Continue without storing converted vertices */
4843         }
4844     }
4845
4846     /* Should I clip?
4847      * a) WINED3DRS_CLIPPING is enabled
4848      * b) WINED3DVOP_CLIP is passed
4849      */
4850     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
4851         static BOOL warned = FALSE;
4852         /*
4853          * The clipping code is not quite correct. Some things need
4854          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4855          * so disable clipping for now.
4856          * (The graphics in Half-Life are broken, and my processvertices
4857          *  test crashes with IDirect3DDevice3)
4858         doClip = TRUE;
4859          */
4860         doClip = FALSE;
4861         if(!warned) {
4862            warned = TRUE;
4863            FIXME("Clipping is broken and disabled for now\n");
4864         }
4865     } else doClip = FALSE;
4866     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4867     if(dest_conv) {
4868         dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4869     }
4870
4871     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4872                                  WINED3DTS_VIEW,
4873                                  &view_mat);
4874     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4875                                  WINED3DTS_PROJECTION,
4876                                  &proj_mat);
4877     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4878                                  WINED3DTS_WORLDMATRIX(0),
4879                                  &world_mat);
4880
4881     TRACE("View mat:\n");
4882     TRACE("%f %f %f %f\n", view_mat.u.s._11, view_mat.u.s._12, view_mat.u.s._13, view_mat.u.s._14); \
4883     TRACE("%f %f %f %f\n", view_mat.u.s._21, view_mat.u.s._22, view_mat.u.s._23, view_mat.u.s._24); \
4884     TRACE("%f %f %f %f\n", view_mat.u.s._31, view_mat.u.s._32, view_mat.u.s._33, view_mat.u.s._34); \
4885     TRACE("%f %f %f %f\n", view_mat.u.s._41, view_mat.u.s._42, view_mat.u.s._43, view_mat.u.s._44); \
4886
4887     TRACE("Proj mat:\n");
4888     TRACE("%f %f %f %f\n", proj_mat.u.s._11, proj_mat.u.s._12, proj_mat.u.s._13, proj_mat.u.s._14); \
4889     TRACE("%f %f %f %f\n", proj_mat.u.s._21, proj_mat.u.s._22, proj_mat.u.s._23, proj_mat.u.s._24); \
4890     TRACE("%f %f %f %f\n", proj_mat.u.s._31, proj_mat.u.s._32, proj_mat.u.s._33, proj_mat.u.s._34); \
4891     TRACE("%f %f %f %f\n", proj_mat.u.s._41, proj_mat.u.s._42, proj_mat.u.s._43, proj_mat.u.s._44); \
4892
4893     TRACE("World mat:\n");
4894     TRACE("%f %f %f %f\n", world_mat.u.s._11, world_mat.u.s._12, world_mat.u.s._13, world_mat.u.s._14); \
4895     TRACE("%f %f %f %f\n", world_mat.u.s._21, world_mat.u.s._22, world_mat.u.s._23, world_mat.u.s._24); \
4896     TRACE("%f %f %f %f\n", world_mat.u.s._31, world_mat.u.s._32, world_mat.u.s._33, world_mat.u.s._34); \
4897     TRACE("%f %f %f %f\n", world_mat.u.s._41, world_mat.u.s._42, world_mat.u.s._43, world_mat.u.s._44); \
4898
4899     /* Get the viewport */
4900     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4901     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
4902           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4903
4904     multiply_matrix(&mat,&view_mat,&world_mat);
4905     multiply_matrix(&mat,&proj_mat,&mat);
4906
4907     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
4908
4909     for (i = 0; i < dwCount; i+= 1) {
4910         unsigned int tex_index;
4911
4912         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
4913              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
4914             /* The position first */
4915             float *p =
4916               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
4917             float x, y, z, rhw;
4918             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4919
4920             /* Multiplication with world, view and projection matrix */
4921             x =   (p[0] * mat.u.s._11) + (p[1] * mat.u.s._21) + (p[2] * mat.u.s._31) + (1.0 * mat.u.s._41);
4922             y =   (p[0] * mat.u.s._12) + (p[1] * mat.u.s._22) + (p[2] * mat.u.s._32) + (1.0 * mat.u.s._42);
4923             z =   (p[0] * mat.u.s._13) + (p[1] * mat.u.s._23) + (p[2] * mat.u.s._33) + (1.0 * mat.u.s._43);
4924             rhw = (p[0] * mat.u.s._14) + (p[1] * mat.u.s._24) + (p[2] * mat.u.s._34) + (1.0 * mat.u.s._44);
4925
4926             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4927
4928             /* WARNING: The following things are taken from d3d7 and were not yet checked
4929              * against d3d8 or d3d9!
4930              */
4931
4932             /* Clipping conditions: From
4933              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4934              *
4935              * A vertex is clipped if it does not match the following requirements
4936              * -rhw < x <= rhw
4937              * -rhw < y <= rhw
4938              *    0 < z <= rhw
4939              *    0 < rhw ( Not in d3d7, but tested in d3d7)
4940              *
4941              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4942              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4943              *
4944              */
4945
4946             if( !doClip ||
4947                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4948                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
4949                   ( rhw > eps ) ) ) {
4950
4951                 /* "Normal" viewport transformation (not clipped)
4952                  * 1) The values are divided by rhw
4953                  * 2) The y axis is negative, so multiply it with -1
4954                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4955                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4956                  * 4) Multiply x with Width/2 and add Width/2
4957                  * 5) The same for the height
4958                  * 6) Add the viewpoint X and Y to the 2D coordinates and
4959                  *    The minimum Z value to z
4960                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4961                  *
4962                  * Well, basically it's simply a linear transformation into viewport
4963                  * coordinates
4964                  */
4965
4966                 x /= rhw;
4967                 y /= rhw;
4968                 z /= rhw;
4969
4970                 y *= -1;
4971
4972                 x *= vp.Width / 2;
4973                 y *= vp.Height / 2;
4974                 z *= vp.MaxZ - vp.MinZ;
4975
4976                 x += vp.Width / 2 + vp.X;
4977                 y += vp.Height / 2 + vp.Y;
4978                 z += vp.MinZ;
4979
4980                 rhw = 1 / rhw;
4981             } else {
4982                 /* That vertex got clipped
4983                  * Contrary to OpenGL it is not dropped completely, it just
4984                  * undergoes a different calculation.
4985                  */
4986                 TRACE("Vertex got clipped\n");
4987                 x += rhw;
4988                 y += rhw;
4989
4990                 x  /= 2;
4991                 y  /= 2;
4992
4993                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
4994                  * outside of the main vertex buffer memory. That needs some more
4995                  * investigation...
4996                  */
4997             }
4998
4999             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5000
5001
5002             ( (float *) dest_ptr)[0] = x;
5003             ( (float *) dest_ptr)[1] = y;
5004             ( (float *) dest_ptr)[2] = z;
5005             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5006
5007             dest_ptr += 3 * sizeof(float);
5008
5009             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
5010                 dest_ptr += sizeof(float);
5011             }
5012
5013             if(dest_conv) {
5014                 float w = 1 / rhw;
5015                 ( (float *) dest_conv)[0] = x * w;
5016                 ( (float *) dest_conv)[1] = y * w;
5017                 ( (float *) dest_conv)[2] = z * w;
5018                 ( (float *) dest_conv)[3] = w;
5019
5020                 dest_conv += 3 * sizeof(float);
5021
5022                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
5023                     dest_conv += sizeof(float);
5024                 }
5025             }
5026         }
5027         if (DestFVF & WINED3DFVF_PSIZE) {
5028             dest_ptr += sizeof(DWORD);
5029             if(dest_conv) dest_conv += sizeof(DWORD);
5030         }
5031         if (DestFVF & WINED3DFVF_NORMAL) {
5032             float *normal =
5033               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5034             /* AFAIK this should go into the lighting information */
5035             FIXME("Didn't expect the destination to have a normal\n");
5036             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5037             if(dest_conv) {
5038                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5039             }
5040         }
5041
5042         if (DestFVF & WINED3DFVF_DIFFUSE) {
5043             DWORD *color_d = 
5044               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5045             if(!color_d) {
5046                 static BOOL warned = FALSE;
5047
5048                 if(!warned) {
5049                     ERR("No diffuse color in source, but destination has one\n");
5050                     warned = TRUE;
5051                 }
5052
5053                 *( (DWORD *) dest_ptr) = 0xffffffff;
5054                 dest_ptr += sizeof(DWORD);
5055
5056                 if(dest_conv) {
5057                     *( (DWORD *) dest_conv) = 0xffffffff;
5058                     dest_conv += sizeof(DWORD);
5059                 }
5060             }
5061             else {
5062                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5063                 if(dest_conv) {
5064                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
5065                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5066                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5067                     dest_conv += sizeof(DWORD);
5068                 }
5069             }
5070         }
5071
5072         if (DestFVF & WINED3DFVF_SPECULAR) { 
5073             /* What's the color value in the feedback buffer? */
5074             DWORD *color_s = 
5075               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5076             if(!color_s) {
5077                 static BOOL warned = FALSE;
5078
5079                 if(!warned) {
5080                     ERR("No specular color in source, but destination has one\n");
5081                     warned = TRUE;
5082                 }
5083
5084                 *( (DWORD *) dest_ptr) = 0xFF000000;
5085                 dest_ptr += sizeof(DWORD);
5086
5087                 if(dest_conv) {
5088                     *( (DWORD *) dest_conv) = 0xFF000000;
5089                     dest_conv += sizeof(DWORD);
5090                 }
5091             }
5092             else {
5093                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5094                 if(dest_conv) {
5095                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
5096                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5097                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5098                     dest_conv += sizeof(DWORD);
5099                 }
5100             }
5101         }
5102
5103         for (tex_index = 0; tex_index < numTextures; tex_index++) {
5104             float *tex_coord =
5105               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
5106                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5107             if(!tex_coord) {
5108                 ERR("No source texture, but destination requests one\n");
5109                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5110                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5111             }
5112             else {
5113                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5114                 if(dest_conv) {
5115                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5116                 }
5117             }
5118         }
5119     }
5120
5121     if(dest_conv) {
5122         GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5123         checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5124     }
5125
5126     LEAVE_GL();
5127
5128     return WINED3D_OK;
5129 }
5130 #undef copy_and_next
5131
5132 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5133     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5134     IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5135     WineDirect3DVertexStridedData strided;
5136     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5137
5138     if (!SrcImpl) {
5139         WARN("NULL source vertex buffer\n");
5140         return WINED3DERR_INVALIDCALL;
5141     }
5142     /* We don't need the source vbo because this buffer is only used as
5143      * a source for ProcessVertices. Avoid wasting resources by converting the
5144      * buffer and loading the VBO
5145      */
5146     if(SrcImpl->vbo) {
5147         TRACE("Releasing the source vbo, it won't be needed\n");
5148
5149         if(!SrcImpl->resource.allocatedMemory) {
5150             /* Rescue the data from the buffer */
5151             void *src;
5152             SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5153             if(!SrcImpl->resource.allocatedMemory) {
5154                 ERR("Out of memory\n");
5155                 return E_OUTOFMEMORY;
5156             }
5157
5158             ENTER_GL();
5159             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5160             checkGLcall("glBindBufferARB");
5161
5162             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5163             if(src) {
5164                 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5165             }
5166
5167             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5168             checkGLcall("glUnmapBufferARB");
5169         } else {
5170             ENTER_GL();
5171         }
5172
5173         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5174         checkGLcall("glBindBufferARB");
5175         GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5176         checkGLcall("glDeleteBuffersARB");
5177         LEAVE_GL();
5178
5179         SrcImpl->vbo = 0;
5180     }
5181
5182     memset(&strided, 0, sizeof(strided));
5183     primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5184
5185     return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5186 }
5187
5188 /*****
5189  * Apply / Get / Set Texture Stage States
5190  * TODO: Verify against dx9 definitions
5191  *****/
5192
5193 /* 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 */
5194 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5195     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5196     DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5197     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5198
5199     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5200
5201     /* Check that the stage is within limits  */
5202     if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5203         TRACE("Attempt to access invalid texture rejected\n");
5204         return;
5205     }
5206
5207     ENTER_GL();
5208
5209     switch (Type) {
5210     case WINED3DTSS_ALPHAOP               :
5211     case WINED3DTSS_COLOROP               :
5212         /* nothing to do as moved to drawprim for now */
5213         break;
5214     case WINED3DTSS_ADDRESSW              :
5215 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5216             if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5217                 FIXME("Unrecognized or unsupported WINED3DTADDRESS_* value %d, state %d\n", Value, Type);
5218
5219             } else {
5220                 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5221                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5222                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5223                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5224             }
5225 #endif
5226     case WINED3DTSS_TEXCOORDINDEX         :
5227         {
5228             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5229
5230             /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5231                   one flag, you can still specify an index value, which the system uses to
5232                   determine the texture wrapping mode.
5233                   eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5234                   means use the vertex position (camera-space) as the input texture coordinates
5235                   for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5236                   state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
5237                   to the TEXCOORDINDEX value */
5238
5239             /**
5240              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5241              */
5242             switch (Value & 0xFFFF0000) {
5243             case WINED3DTSS_TCI_PASSTHRU:
5244                 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5245                 glDisable(GL_TEXTURE_GEN_S);
5246                 glDisable(GL_TEXTURE_GEN_T);
5247                 glDisable(GL_TEXTURE_GEN_R);
5248                 glDisable(GL_TEXTURE_GEN_Q);
5249                 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5250                 break;
5251
5252             case WINED3DTSS_TCI_CAMERASPACEPOSITION:
5253                 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5254                     as the input texture coordinates for this stage's texture transformation. This
5255                     equates roughly to EYE_LINEAR                                                  */
5256                 {
5257                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5258                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5259                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5260                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5261                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5262     
5263                     glMatrixMode(GL_MODELVIEW);
5264                     glPushMatrix();
5265                     glLoadIdentity();
5266                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5267                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5268                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5269                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5270                     glPopMatrix();
5271     
5272                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5273                     glEnable(GL_TEXTURE_GEN_S);
5274                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5275                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5276                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5277                     glEnable(GL_TEXTURE_GEN_T);
5278                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5279                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5280                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5281                     glEnable(GL_TEXTURE_GEN_R);
5282                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5283                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5284                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5285                 }
5286                 break;
5287
5288             case WINED3DTSS_TCI_CAMERASPACENORMAL:
5289                 {
5290                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5291                         float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5292                         float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5293                         float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5294                         float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5295                         TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5296         
5297                         glMatrixMode(GL_MODELVIEW);
5298                         glPushMatrix();
5299                         glLoadIdentity();
5300                         glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5301                         glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5302                         glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5303                         glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5304                         glPopMatrix();
5305         
5306                         glEnable(GL_TEXTURE_GEN_S);
5307                         checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5308                         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5309                         checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5310                         glEnable(GL_TEXTURE_GEN_T);
5311                         checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5312                         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5313                         checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5314                         glEnable(GL_TEXTURE_GEN_R);
5315                         checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5316                         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5317                         checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5318                     }
5319                 }
5320                 break;
5321
5322             case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5323                 {
5324                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5325                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5326                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5327                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5328                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5329                     TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5330     
5331                     glMatrixMode(GL_MODELVIEW);
5332                     glPushMatrix();
5333                     glLoadIdentity();
5334                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5335                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5336                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5337                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5338                     glPopMatrix();
5339     
5340                     glEnable(GL_TEXTURE_GEN_S);
5341                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5342                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5343                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5344                     glEnable(GL_TEXTURE_GEN_T);
5345                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5346                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5347                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5348                     glEnable(GL_TEXTURE_GEN_R);
5349                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5350                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5351                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5352                     }
5353                 }
5354                 break;
5355
5356             /* Unhandled types: */
5357             default:
5358                 /* Todo: */
5359                 /* ? disable GL_TEXTURE_GEN_n ? */
5360                 glDisable(GL_TEXTURE_GEN_S);
5361                 glDisable(GL_TEXTURE_GEN_T);
5362                 glDisable(GL_TEXTURE_GEN_R);
5363                 glDisable(GL_TEXTURE_GEN_Q);
5364                 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", Value);
5365                 break;
5366             }
5367         }
5368         break;
5369
5370         /* Unhandled */
5371     case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5372         set_texture_matrix((float *)&This->stateBlock->transforms[WINED3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU);
5373         break;
5374
5375     case WINED3DTSS_BUMPENVMAT00          :
5376     case WINED3DTSS_BUMPENVMAT01          :
5377         TRACE("BUMPENVMAT0%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5378         break;
5379     case WINED3DTSS_BUMPENVMAT10          :
5380     case WINED3DTSS_BUMPENVMAT11          :
5381         TRACE("BUMPENVMAT1%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5382         break;
5383
5384     case WINED3DTSS_BUMPENVLSCALE         :
5385       TRACE("BUMPENVLSCALE Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5386       break;
5387
5388     case WINED3DTSS_BUMPENVLOFFSET        :
5389       TRACE("BUMPENVLOFFSET Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5390       break;
5391
5392     case WINED3DTSS_RESULTARG             :
5393       TRACE("RESULTARG Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5394       break;
5395
5396     default:
5397         /* Put back later: FIXME("(%p) : stub, Stage=%d, Type=%d, Value =%d\n", This, Stage, Type, Value); */
5398         TRACE("Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5399     }
5400
5401     LEAVE_GL();
5402
5403     return;
5404 }
5405
5406 /*****
5407  * Get / Set Texture Stage States
5408  * TODO: Verify against dx9 definitions
5409  *****/
5410 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5411     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5412
5413     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5414
5415     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5416
5417     /* Reject invalid texture units */
5418     if (Stage >= GL_LIMITS(texture_stages)) {
5419         TRACE("Attempt to access invalid texture rejected\n");
5420         return WINED3DERR_INVALIDCALL;
5421     }
5422
5423     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5424     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
5425     This->updateStateBlock->textureState[Stage][Type]         = Value;
5426
5427     return WINED3D_OK;
5428 }
5429
5430 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5431     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5432     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5433     *pValue = This->updateStateBlock->textureState[Stage][Type];
5434     return WINED3D_OK;
5435 }
5436
5437 /*****
5438  * Get / Set Texture
5439  *****/
5440 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5441
5442     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5443     IWineD3DBaseTexture   *oldTexture;
5444
5445     oldTexture = This->updateStateBlock->textures[Stage];
5446     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
5447
5448 #if 0 /* TODO: check so vertex textures */
5449     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5450         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5451         return WINED3D_OK;
5452     }
5453 #endif
5454
5455     /* Reject invalid texture units */
5456     if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5457         WARN("Attempt to access invalid texture rejected\n");
5458         return WINED3DERR_INVALIDCALL;
5459     }
5460
5461     if(pTexture != NULL) {
5462         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
5463          */
5464         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5465             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5466             return WINED3DERR_INVALIDCALL;
5467         }
5468     }
5469
5470     oldTexture = This->updateStateBlock->textures[Stage];
5471     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5472     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5473
5474     This->updateStateBlock->set.textures[Stage]     = TRUE;
5475     This->updateStateBlock->changed.textures[Stage] = TRUE;
5476     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5477     This->updateStateBlock->textures[Stage]         = pTexture;
5478
5479     /* Handle recording of state blocks */
5480     if (This->isRecordingState) {
5481         TRACE("Recording... not performing anything\n");
5482         return WINED3D_OK;
5483     }
5484
5485     /** NOTE: MSDN says that setTexture increases the reference count,
5486     * and the the application nust set the texture back to null (or have a leaky application),
5487     * This means we should pass the refcount up to the parent
5488      *******************************/
5489     if (NULL != This->updateStateBlock->textures[Stage]) {
5490         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5491     }
5492
5493     if (NULL != oldTexture) {
5494         IWineD3DBaseTexture_Release(oldTexture);
5495     }
5496
5497     /* Reset color keying */
5498     if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5499         BOOL enable_ckey = FALSE;
5500
5501         if(pTexture) {
5502             IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5503             if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5504         }
5505
5506         if(enable_ckey) {
5507             glAlphaFunc(GL_NOTEQUAL, 0.0);
5508             checkGLcall("glAlphaFunc");
5509         }
5510     }
5511
5512     return WINED3D_OK;
5513 }
5514
5515 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5516     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5517     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5518
5519     /* Reject invalid texture units */
5520     if (Stage >= GL_LIMITS(sampler_stages)) {
5521         TRACE("Attempt to access invalid texture rejected\n");
5522         return WINED3DERR_INVALIDCALL;
5523     }
5524     *ppTexture=This->stateBlock->textures[Stage];
5525     if (*ppTexture)
5526         IWineD3DBaseTexture_AddRef(*ppTexture);
5527
5528     return WINED3D_OK;
5529 }
5530
5531 /*****
5532  * Get Back Buffer
5533  *****/
5534 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5535                                                 IWineD3DSurface **ppBackBuffer) {
5536     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5537     IWineD3DSwapChain *swapChain;
5538     HRESULT hr;
5539
5540     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5541
5542     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
5543     if (hr == WINED3D_OK) {
5544         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5545             IWineD3DSwapChain_Release(swapChain);
5546     } else {
5547         *ppBackBuffer = NULL;
5548     }
5549     return hr;
5550 }
5551
5552 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5553     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5554     WARN("(%p) : stub, calling idirect3d for now\n", This);
5555     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5556 }
5557
5558 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5559     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5560     IWineD3DSwapChain *swapChain;
5561     HRESULT hr;
5562
5563     if(iSwapChain > 0) {
5564         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5565         if (hr == WINED3D_OK) {
5566             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5567             IWineD3DSwapChain_Release(swapChain);
5568         } else {
5569             FIXME("(%p) Error getting display mode\n", This);
5570         }
5571     } else {
5572         /* Don't read the real display mode,
5573            but return the stored mode instead. X11 can't change the color
5574            depth, and some apps are pretty angry if they SetDisplayMode from
5575            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5576
5577            Also don't relay to the swapchain because with ddraw it's possible
5578            that there isn't a swapchain at all */
5579         pMode->Width = This->ddraw_width;
5580         pMode->Height = This->ddraw_height;
5581         pMode->Format = This->ddraw_format;
5582         pMode->RefreshRate = 0;
5583         hr = WINED3D_OK;
5584     }
5585
5586     return hr;
5587 }
5588
5589 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5590     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5591     TRACE("(%p)->(%p)\n", This, hWnd);
5592
5593     This->ddraw_window = hWnd;
5594     return WINED3D_OK;
5595 }
5596
5597 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5598     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5599     TRACE("(%p)->(%p)\n", This, hWnd);
5600
5601     *hWnd = This->ddraw_window;
5602     return WINED3D_OK;
5603 }
5604
5605 /*****
5606  * Stateblock related functions
5607  *****/
5608
5609 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5610     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5611     IWineD3DStateBlockImpl *object;
5612     HRESULT temp_result;
5613     
5614     TRACE("(%p)\n", This);
5615     
5616     if (This->isRecordingState) {
5617         return WINED3DERR_INVALIDCALL;
5618     }
5619     
5620     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5621     if (NULL == object ) {
5622         FIXME("(%p)Error allocating memory for stateblock\n", This);
5623         return E_OUTOFMEMORY;
5624     }
5625     TRACE("(%p) created object %p\n", This, object);
5626     object->wineD3DDevice= This;
5627     /** FIXME: object->parent       = parent; **/
5628     object->parent       = NULL;
5629     object->blockType    = WINED3DSBT_ALL;
5630     object->ref          = 1;
5631     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
5632     
5633     temp_result = allocate_shader_constants(object);
5634     if (WINED3D_OK != temp_result)
5635         return temp_result;
5636
5637     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5638     This->updateStateBlock = object;
5639     This->isRecordingState = TRUE;
5640
5641     TRACE("(%p) recording stateblock %p\n",This , object);
5642     return WINED3D_OK;
5643 }
5644
5645 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5646     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5647
5648     if (!This->isRecordingState) {
5649         FIXME("(%p) not recording! returning error\n", This);
5650         *ppStateBlock = NULL;
5651         return WINED3DERR_INVALIDCALL;
5652     }
5653
5654     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5655     This->isRecordingState = FALSE;
5656     This->updateStateBlock = This->stateBlock;
5657     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5658     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5659     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5660     return WINED3D_OK;
5661 }
5662
5663 /*****
5664  * Scene related functions
5665  *****/
5666 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5667     /* At the moment we have no need for any functionality at the beginning
5668        of a scene                                                          */
5669     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5670     TRACE("(%p) : stub\n", This);
5671     return WINED3D_OK;
5672 }
5673
5674 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5675     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5676     TRACE("(%p)\n", This);
5677     ENTER_GL();
5678     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5679     glFlush();
5680     checkGLcall("glFlush");
5681
5682     TRACE("End Scene\n");
5683     /* If we're using FBOs this isn't needed */
5684     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->renderTarget != NULL) {
5685
5686         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5687         IUnknown *targetContainer = NULL;
5688         if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5689             || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5690             TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5691             /** always dirtify for now. we must find a better way to see that surface have been modified
5692             (Modifications should will only occur via draw-primitive, but we do need better locking
5693             switching to render-to-texture should remove the overhead though.
5694             */
5695             IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5696             IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5697             IWineD3DSurface_PreLoad(This->renderTarget);
5698             IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5699             IUnknown_Release(targetContainer);
5700         }
5701     }
5702     This->sceneEnded = TRUE;
5703     LEAVE_GL();
5704     return WINED3D_OK;
5705 }
5706
5707 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
5708                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
5709                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
5710     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5711     IWineD3DSwapChain *swapChain = NULL;
5712     int i;
5713     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
5714
5715     TRACE("(%p) Presenting the frame\n", This);
5716
5717     for(i = 0 ; i < swapchains ; i ++) {
5718
5719         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
5720         TRACE("presentinng chain %d, %p\n", i, swapChain);
5721         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
5722         IWineD3DSwapChain_Release(swapChain);
5723     }
5724
5725     return WINED3D_OK;
5726 }
5727
5728 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
5729                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
5730     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5731
5732     /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
5733       render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
5734       when the depth-buffer format does not contain stencil buffer information, this method fails. */
5735     GLbitfield     glMask = 0;
5736     GLboolean      old_ztest;
5737     GLfloat        old_z_clear_value;
5738     GLint          old_stencil_clear_value;
5739     GLfloat        old_color_clear_value[4];
5740     unsigned int   i;
5741     CONST WINED3DRECT* curRect;
5742
5743     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
5744           Count, pRects, Flags, Z, Stencil);
5745
5746     ENTER_GL();
5747
5748     glEnable(GL_SCISSOR_TEST);
5749     checkGLcall("glEnable GL_SCISSOR_TEST");
5750
5751     if (Count > 0 && pRects) {
5752         curRect = pRects;
5753     } else {
5754         curRect = NULL;
5755     }
5756
5757     /* Only set the values up once, as they are not changing */
5758     if (Flags & WINED3DCLEAR_STENCIL) {
5759         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
5760         glClearStencil(Stencil);
5761         checkGLcall("glClearStencil");
5762         glMask = glMask | GL_STENCIL_BUFFER_BIT;
5763         glStencilMask(0xFFFFFFFF);
5764     }
5765
5766     if (Flags & WINED3DCLEAR_ZBUFFER) {
5767         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
5768         glDepthMask(GL_TRUE);
5769         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
5770         glClearDepth(Z);
5771         checkGLcall("glClearDepth");
5772         glMask = glMask | GL_DEPTH_BUFFER_BIT;
5773     }
5774
5775     if (Flags & WINED3DCLEAR_TARGET) {
5776         TRACE("Clearing screen with glClear to color %x\n", Color);
5777         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
5778         glClearColor(D3DCOLOR_R(Color),
5779                      D3DCOLOR_G(Color),
5780                      D3DCOLOR_B(Color),
5781                      D3DCOLOR_A(Color));
5782         checkGLcall("glClearColor");
5783
5784         /* Clear ALL colors! */
5785         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5786         glMask = glMask | GL_COLOR_BUFFER_BIT;
5787     }
5788
5789     /* Now process each rect in turn */
5790     for (i = 0; i < Count || i == 0; i++) {
5791
5792         if (curRect) {
5793             /* Note gl uses lower left, width/height */
5794             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
5795                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
5796                   curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5797                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5798             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
5799                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
5800             checkGLcall("glScissor");
5801         } else {
5802             glScissor(This->stateBlock->viewport.X,
5803                       (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - 
5804                       (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
5805                       This->stateBlock->viewport.Width,
5806                       This->stateBlock->viewport.Height);
5807             checkGLcall("glScissor");
5808         }
5809
5810         /* Clear the selected rectangle (or full screen) */
5811         glClear(glMask);
5812         checkGLcall("glClear");
5813
5814         /* Step to the next rectangle */
5815         if (curRect) curRect = curRect + sizeof(WINED3DRECT);
5816     }
5817
5818     /* Restore the old values (why..?) */
5819     if (Flags & WINED3DCLEAR_STENCIL) {
5820         glClearStencil(old_stencil_clear_value);
5821         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5822     }
5823     if (Flags & WINED3DCLEAR_ZBUFFER) {
5824         glDepthMask(old_ztest);
5825         glClearDepth(old_z_clear_value);
5826     }
5827     if (Flags & WINED3DCLEAR_TARGET) {
5828         glClearColor(old_color_clear_value[0],
5829                      old_color_clear_value[1],
5830                      old_color_clear_value[2],
5831                      old_color_clear_value[3]);
5832         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5833                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5834                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
5835                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5836     }
5837
5838     glDisable(GL_SCISSOR_TEST);
5839     checkGLcall("glDisable");
5840     LEAVE_GL();
5841
5842     return WINED3D_OK;
5843 }
5844
5845 /*****
5846  * Drawing functions
5847  *****/
5848 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5849                                                 UINT PrimitiveCount) {
5850
5851     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5852     This->stateBlock->streamIsUP = FALSE;
5853
5854     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5855                                debug_d3dprimitivetype(PrimitiveType),
5856                                StartVertex, PrimitiveCount);
5857     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5858                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
5859
5860
5861     return WINED3D_OK;
5862 }
5863
5864 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5865 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5866                                                            WINED3DPRIMITIVETYPE PrimitiveType,
5867                                                            INT baseVIndex, UINT minIndex,
5868                                                            UINT NumVertices, UINT startIndex, UINT primCount) {
5869
5870     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
5871     UINT                 idxStride = 2;
5872     IWineD3DIndexBuffer *pIB;
5873     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
5874
5875     pIB = This->stateBlock->pIndexData;
5876     This->stateBlock->streamIsUP = FALSE;
5877
5878     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
5879           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5880           minIndex, NumVertices, startIndex, baseVIndex, primCount);
5881
5882     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5883     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5884         idxStride = 2;
5885     } else {
5886         idxStride = 4;
5887     }
5888
5889     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
5890                    idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
5891
5892     return WINED3D_OK;
5893 }
5894
5895 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5896                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5897                                                     UINT VertexStreamZeroStride) {
5898     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5899
5900     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5901              debug_d3dprimitivetype(PrimitiveType),
5902              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5903
5904     /* release the stream source */
5905     if (This->stateBlock->streamSource[0] != NULL) {
5906         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5907     }
5908
5909     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5910     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5911     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5912     This->stateBlock->streamIsUP = TRUE;
5913
5914     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
5915                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
5916
5917     /* MSDN specifies stream zero settings must be set to NULL */
5918     This->stateBlock->streamStride[0] = 0;
5919     This->stateBlock->streamSource[0] = NULL;
5920
5921     /*stream zero settings set to null at end, as per the msdn */
5922     return WINED3D_OK;
5923 }
5924
5925 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5926                                                              UINT MinVertexIndex, UINT NumVertices,
5927                                                              UINT PrimitiveCount, CONST void* pIndexData,
5928                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5929                                                              UINT VertexStreamZeroStride) {
5930     int                 idxStride;
5931     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5932
5933     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5934              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5935              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5936              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5937
5938     if (IndexDataFormat == WINED3DFMT_INDEX16) {
5939         idxStride = 2;
5940     } else {
5941         idxStride = 4;
5942     }
5943
5944     /* release the stream and index data */
5945     if (This->stateBlock->streamSource[0] != NULL) {
5946         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5947     }
5948     if (This->stateBlock->pIndexData) {
5949         IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5950     }
5951
5952     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5953     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5954     This->stateBlock->streamIsUP = TRUE;
5955     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5956
5957     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
5958
5959     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5960     This->stateBlock->streamSource[0] = NULL;
5961     This->stateBlock->streamStride[0] = 0;
5962     This->stateBlock->pIndexData = NULL;
5963
5964     return WINED3D_OK;
5965 }
5966
5967 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5968
5969     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5970     return WINED3D_OK;
5971 }
5972  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5973 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
5974     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5975     HRESULT hr = WINED3D_OK;
5976     WINED3DRESOURCETYPE sourceType;
5977     WINED3DRESOURCETYPE destinationType;
5978     int i ,levels;
5979
5980     /* TODO: think about moving the code into IWineD3DBaseTexture  */
5981
5982     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5983
5984     /* verify that the source and destination textures aren't NULL */
5985     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5986         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5987              This, pSourceTexture, pDestinationTexture);
5988         hr = WINED3DERR_INVALIDCALL;
5989     }
5990
5991     if (pSourceTexture == pDestinationTexture) {
5992         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5993              This, pSourceTexture, pDestinationTexture);
5994         hr = WINED3DERR_INVALIDCALL;
5995     }
5996     /* Verify that the source and destination textures are the same type */
5997     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5998     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5999
6000     if (sourceType != destinationType) {
6001         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6002              This);
6003         hr = WINED3DERR_INVALIDCALL;
6004     }
6005
6006     /* check that both textures have the identical numbers of levels  */
6007     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6008         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6009         hr = WINED3DERR_INVALIDCALL;
6010     }
6011
6012     if (WINED3D_OK == hr) {
6013
6014         /* Make sure that the destination texture is loaded */
6015         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6016
6017         /* Update every surface level of the texture */
6018         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6019
6020         switch (sourceType) {
6021         case WINED3DRTYPE_TEXTURE:
6022             {
6023                 IWineD3DSurface *srcSurface;
6024                 IWineD3DSurface *destSurface;
6025
6026                 for (i = 0 ; i < levels ; ++i) {
6027                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
6028                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6029                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6030                     IWineD3DSurface_Release(srcSurface);
6031                     IWineD3DSurface_Release(destSurface);
6032                     if (WINED3D_OK != hr) {
6033                         WARN("(%p) : Call to update surface failed\n", This);
6034                         return hr;
6035                     }
6036                 }
6037             }
6038             break;
6039         case WINED3DRTYPE_CUBETEXTURE:
6040             {
6041                 IWineD3DSurface *srcSurface;
6042                 IWineD3DSurface *destSurface;
6043                 WINED3DCUBEMAP_FACES faceType;
6044
6045                 for (i = 0 ; i < levels ; ++i) {
6046                     /* Update each cube face */
6047                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6048                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
6049                         if (WINED3D_OK != hr) {
6050                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6051                         } else {
6052                             TRACE("Got srcSurface %p\n", srcSurface);
6053                         }
6054                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6055                         if (WINED3D_OK != hr) {
6056                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6057                         } else {
6058                             TRACE("Got desrSurface %p\n", destSurface);
6059                         }
6060                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6061                         IWineD3DSurface_Release(srcSurface);
6062                         IWineD3DSurface_Release(destSurface);
6063                         if (WINED3D_OK != hr) {
6064                             WARN("(%p) : Call to update surface failed\n", This);
6065                             return hr;
6066                         }
6067                     }
6068                 }
6069             }
6070             break;
6071 #if 0 /* TODO: Add support for volume textures */
6072         case WINED3DRTYPE_VOLUMETEXTURE:
6073             {
6074                 IWineD3DVolume  srcVolume  = NULL;
6075                 IWineD3DSurface destVolume = NULL;
6076
6077                 for (i = 0 ; i < levels ; ++i) {
6078                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
6079                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6080                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6081                     IWineD3DVolume_Release(srcSurface);
6082                     IWineD3DVolume_Release(destSurface);
6083                     if (WINED3D_OK != hr) {
6084                         WARN("(%p) : Call to update volume failed\n", This);
6085                         return hr;
6086                     }
6087                 }
6088             }
6089             break;
6090 #endif
6091         default:
6092             FIXME("(%p) : Unsupported source and destination type\n", This);
6093             hr = WINED3DERR_INVALIDCALL;
6094         }
6095     }
6096
6097     return hr;
6098 }
6099
6100 static HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6101                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6102                                                 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6103     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6104
6105     TRACE("(%p) : stub\n", This);
6106     return WINED3D_OK;
6107 }
6108 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6109     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6110     /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6111     *  NOTE It may be best to move the code into surface to occomplish this
6112     ****************************************/
6113
6114     WINED3DSURFACE_DESC surfaceDesc;
6115     unsigned int surfaceWidth, surfaceHeight;
6116     glDescriptor *targetGlDescription  = NULL;
6117     glDescriptor *surfaceGlDescription = NULL;
6118     IWineD3DSwapChainImpl *container = NULL;
6119     
6120     IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6121     IWineD3DSurface_GetGlDesc(pSurface,      &surfaceGlDescription);
6122     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6123
6124     surfaceDesc.Width  = &surfaceWidth;
6125     surfaceDesc.Height = &surfaceHeight;
6126     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6127    /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6128
6129     /* Ok, I may need to setup some kind of active swapchain reference on the device */
6130     IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6131     ENTER_GL();
6132     /* TODO: opengl Context switching for swapchains etc... */
6133     if (NULL != container  || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6134         if (NULL != container  && (pRenderTarget == container->backBuffer[0])) {
6135             glReadBuffer(GL_BACK);
6136             vcheckGLcall("glReadBuffer(GL_BACK)");
6137         } else if ((NULL != container  && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6138             glReadBuffer(GL_FRONT);
6139             vcheckGLcall("glReadBuffer(GL_FRONT)");
6140         } else if (pRenderTarget == This->depthStencilBuffer) {
6141             FIXME("Reading of depthstencil not yet supported\n");
6142         }
6143
6144         glReadPixels(0,
6145                     0,
6146                     surfaceWidth,
6147                     surfaceHeight,
6148                     surfaceGlDescription->glFormat,
6149                     surfaceGlDescription->glType,
6150                     (void *)IWineD3DSurface_GetData(pSurface));
6151         vcheckGLcall("glReadPixels(...)");
6152         if(NULL != container ){
6153             IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6154         }
6155     } else {
6156         IWineD3DBaseTexture *container;
6157         GLenum textureDimensions = GL_TEXTURE_2D;
6158
6159         if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6160             textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6161             IWineD3DBaseTexture_Release(container);
6162         }
6163         /* TODO: 2D -> Cube surface coppies etc.. */
6164         if (surfaceGlDescription->target != textureDimensions) {
6165             FIXME("(%p) : Texture dimension mismatch\n", This);
6166         }
6167         glEnable(textureDimensions);
6168         vcheckGLcall("glEnable(GL_TEXTURE_...)");
6169         /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6170         glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6171         vcheckGLcall("glBindTexture");
6172         glGetTexImage(surfaceGlDescription->target,
6173                         surfaceGlDescription->level,
6174                         surfaceGlDescription->glFormat,
6175                         surfaceGlDescription->glType,
6176                         (void *)IWineD3DSurface_GetData(pSurface));
6177         glDisable(textureDimensions);
6178         vcheckGLcall("glDisable(GL_TEXTURE_...)");
6179
6180     }
6181     LEAVE_GL();
6182     return WINED3D_OK;
6183 }
6184
6185 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6186     IWineD3DSwapChain *swapChain;
6187     HRESULT hr;
6188     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
6189     if(hr == WINED3D_OK) {
6190         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6191                 IWineD3DSwapChain_Release(swapChain);
6192     }
6193     return hr;
6194 }
6195
6196 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6197     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6198     /* return a sensible default */
6199     *pNumPasses = 1;
6200     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6201     FIXME("(%p) : stub\n", This);
6202     return WINED3D_OK;
6203 }
6204
6205 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6206     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6207     int j;
6208     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6209     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6210         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6211         return WINED3DERR_INVALIDCALL;
6212     }
6213     for (j = 0; j < 256; ++j) {
6214         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
6215         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6216         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
6217         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6218     }
6219     TRACE("(%p) : returning\n", This);
6220     return WINED3D_OK;
6221 }
6222
6223 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6224     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6225     int j;
6226     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6227     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6228         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6229         return WINED3DERR_INVALIDCALL;
6230     }
6231     for (j = 0; j < 256; ++j) {
6232         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
6233         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6234         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
6235         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6236     }
6237     TRACE("(%p) : returning\n", This);
6238     return WINED3D_OK;
6239 }
6240
6241 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6242     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6243     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6244     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6245         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6246         return WINED3DERR_INVALIDCALL;
6247     }
6248     /*TODO: stateblocks */
6249     This->currentPalette = PaletteNumber;
6250     TRACE("(%p) : returning\n", This);
6251     return WINED3D_OK;
6252 }
6253
6254 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6255     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6256     if (PaletteNumber == NULL) {
6257         WARN("(%p) : returning Invalid Call\n", This);
6258         return WINED3DERR_INVALIDCALL;
6259     }
6260     /*TODO: stateblocks */
6261     *PaletteNumber = This->currentPalette;
6262     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
6263     return WINED3D_OK;
6264 }
6265
6266 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6267     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6268     static BOOL showFixmes = TRUE;
6269     if (showFixmes) {
6270         FIXME("(%p) : stub\n", This);
6271         showFixmes = FALSE;
6272     }
6273
6274     This->softwareVertexProcessing = bSoftware;
6275     return WINED3D_OK;
6276 }
6277
6278
6279 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6280     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6281     static BOOL showFixmes = TRUE;
6282     if (showFixmes) {
6283         FIXME("(%p) : stub\n", This);
6284         showFixmes = FALSE;
6285     }
6286     return This->softwareVertexProcessing;
6287 }
6288
6289
6290 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6291     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6292     IWineD3DSwapChain *swapChain;
6293     HRESULT hr;
6294
6295     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6296
6297     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
6298     if(hr == WINED3D_OK){
6299         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6300         IWineD3DSwapChain_Release(swapChain);
6301     }else{
6302         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6303     }
6304     return hr;
6305 }
6306
6307
6308 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6309     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6310     static BOOL showfixmes = TRUE;
6311     if(nSegments != 0.0f) {
6312         if( showfixmes) {
6313             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6314             showfixmes = FALSE;
6315         }
6316     }
6317     return WINED3D_OK;
6318 }
6319
6320 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6321     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6322     static BOOL showfixmes = TRUE;
6323     if( showfixmes) {
6324         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6325         showfixmes = FALSE;
6326     }
6327     return 0.0f;
6328 }
6329
6330 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6331     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
6332     /** TODO: remove casts to IWineD3DSurfaceImpl
6333      *       NOTE: move code to surface to accomplish this
6334       ****************************************/
6335     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
6336     int srcWidth, srcHeight;
6337     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6338     WINED3DFORMAT destFormat, srcFormat;
6339     UINT          destSize;
6340     int destLeft, destTop;
6341     WINED3DPOOL       srcPool, destPool;
6342     int offset    = 0;
6343     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6344     glDescriptor *glDescription = NULL;
6345     GLenum textureDimensions = GL_TEXTURE_2D;
6346     IWineD3DBaseTexture *baseTexture;
6347
6348     WINED3DSURFACE_DESC  winedesc;
6349
6350     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6351     memset(&winedesc, 0, sizeof(winedesc));
6352     winedesc.Width  = &srcSurfaceWidth;
6353     winedesc.Height = &srcSurfaceHeight;
6354     winedesc.Pool   = &srcPool;
6355     winedesc.Format = &srcFormat;
6356
6357     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6358
6359     winedesc.Width  = &destSurfaceWidth;
6360     winedesc.Height = &destSurfaceHeight;
6361     winedesc.Pool   = &destPool;
6362     winedesc.Format = &destFormat;
6363     winedesc.Size   = &destSize;
6364
6365     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6366
6367     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
6368         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6369         return WINED3DERR_INVALIDCALL;
6370     }
6371
6372     if (destFormat == WINED3DFMT_UNKNOWN) {
6373         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6374         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6375
6376         /* Get the update surface description */
6377         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6378     }
6379
6380     /* Make sure the surface is loaded and up to date */
6381     IWineD3DSurface_PreLoad(pDestinationSurface);
6382
6383     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6384
6385     ENTER_GL();
6386
6387     /* this needs to be done in lines if the sourceRect != the sourceWidth */
6388     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
6389     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
6390     destLeft   = pDestPoint  ? pDestPoint->x : 0;
6391     destTop    = pDestPoint  ? pDestPoint->y : 0;
6392
6393
6394     /* This function doesn't support compressed textures
6395     the pitch is just bytesPerPixel * width */
6396     if(srcWidth != srcSurfaceWidth  || (pSourceRect != NULL && pSourceRect->left != 0) ){
6397         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6398         offset   += pSourceRect->left * pSrcSurface->bytesPerPixel;
6399         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6400     }
6401     /* TODO DXT formats */
6402
6403     if(pSourceRect != NULL && pSourceRect->top != 0){
6404        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6405     }
6406     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6407     ,This
6408     ,glDescription->level
6409     ,destLeft
6410     ,destTop
6411     ,srcWidth
6412     ,srcHeight
6413     ,glDescription->glFormat
6414     ,glDescription->glType
6415     ,IWineD3DSurface_GetData(pSourceSurface)
6416     );
6417
6418     /* Sanity check */
6419     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6420
6421         /* need to lock the surface to get the data */
6422         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6423     }
6424
6425     /* TODO: Cube and volume support */
6426     if(rowoffset != 0){
6427         /* not a whole row so we have to do it a line at a time */
6428         int j;
6429
6430         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6431         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6432
6433         for(j = destTop ; j < (srcHeight + destTop) ; j++){
6434
6435                 glTexSubImage2D(glDescription->target
6436                     ,glDescription->level
6437                     ,destLeft
6438                     ,j
6439                     ,srcWidth
6440                     ,1
6441                     ,glDescription->glFormat
6442                     ,glDescription->glType
6443                     ,data /* could be quicker using */
6444                 );
6445             data += rowoffset;
6446         }
6447
6448     } else { /* Full width, so just write out the whole texture */
6449
6450         if (WINED3DFMT_DXT1 == destFormat ||
6451             WINED3DFMT_DXT2 == destFormat ||
6452             WINED3DFMT_DXT3 == destFormat ||
6453             WINED3DFMT_DXT4 == destFormat ||
6454             WINED3DFMT_DXT5 == destFormat) {
6455             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6456                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6457                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
6458                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
6459                 } if (destFormat != srcFormat) {
6460                     FIXME("Updating mixed format compressed texture is not curretly support\n");
6461                 } else {
6462                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6463                                                         glDescription->level,
6464                                                         glDescription->glFormatInternal,
6465                                                         srcWidth,
6466                                                         srcHeight,
6467                                                         0,
6468                                                         destSize,
6469                                                         IWineD3DSurface_GetData(pSourceSurface));
6470                 }
6471             } else {
6472                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6473             }
6474
6475
6476         } else {
6477             if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6478
6479                 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6480                 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6481                 data returned by GetData non-power2 width/height with hardware non-power2
6482                 pow2Width/height are set to surface width height, repacking isn't needed so it
6483                 doesn't matter which function gets called. */
6484                 glTexSubImage2D(glDescription->target
6485                         ,glDescription->level
6486                         ,destLeft
6487                         ,destTop
6488                         ,srcWidth
6489                         ,srcHeight
6490                         ,glDescription->glFormat
6491                         ,glDescription->glType
6492                         ,IWineD3DSurface_GetData(pSourceSurface)
6493                     );
6494             } else {
6495
6496                 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6497                 glTexSubImage2D(glDescription->target
6498                     ,glDescription->level
6499                     ,destLeft
6500                     ,destTop
6501                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6502                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6503                     ,glDescription->glFormat
6504                     ,glDescription->glType
6505                     ,IWineD3DSurface_GetData(pSourceSurface)
6506                 );
6507             }
6508
6509         }
6510      }
6511     checkGLcall("glTexSubImage2D");
6512     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
6513
6514     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6515      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6516      * surface bigger than it needs to be hmm.. */
6517     if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6518         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6519         IWineD3DBaseTexture_Release(baseTexture);
6520     }
6521
6522     glDisable(textureDimensions); /* This needs to be managed better.... */
6523     LEAVE_GL();
6524
6525     return WINED3D_OK;
6526 }
6527
6528 /* Implementation details at http://developer.nvidia.com/attach/6494
6529 and
6530 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6531 hmm.. no longer supported use
6532 OpenGL evaluators or  tessellate surfaces within your application.
6533 */
6534
6535 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6536 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6537     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6538     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6539     FIXME("(%p) : Stub\n", This);
6540     return WINED3D_OK;
6541
6542 }
6543
6544 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6545 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6546     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6547     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6548     FIXME("(%p) : Stub\n", This);
6549     return WINED3D_OK;
6550 }
6551
6552 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6553     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6554     TRACE("(%p) Handle(%d)\n", This, Handle);
6555     FIXME("(%p) : Stub\n", This);
6556     return WINED3D_OK;
6557 }
6558
6559 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
6560     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6561     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6562     DDBLTFX BltFx;
6563     TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
6564
6565     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6566         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6567         return WINED3DERR_INVALIDCALL;
6568     }
6569
6570     /* Just forward this to the DirectDraw blitting engine */
6571     memset(&BltFx, 0, sizeof(BltFx));
6572     BltFx.dwSize = sizeof(BltFx);
6573     BltFx.u5.dwFillColor = color;
6574     return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
6575 }
6576
6577 /* rendertarget and deptth stencil functions */
6578 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6579     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6580
6581     /* FIXME: Implelent RenderTargetIndex >0 */
6582     if(RenderTargetIndex > 0)
6583         FIXME("(%p) : RenderTargetIndex %d >0 not currently supported\n", This, RenderTargetIndex);
6584
6585     *ppRenderTarget = This->renderTarget;
6586     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6587     /* Note inc ref on returned surface */
6588     if(*ppRenderTarget != NULL)
6589         IWineD3DSurface_AddRef(*ppRenderTarget);
6590     return WINED3D_OK;
6591 }
6592
6593 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6594     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6595     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6596     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6597     IWineD3DSwapChainImpl *Swapchain;
6598     HRESULT hr;
6599
6600     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6601
6602     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6603     if(hr != WINED3D_OK) {
6604         ERR("Can't get the swapchain\n");
6605         return hr;
6606     }
6607
6608     /* Make sure to release the swapchain */
6609     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6610
6611     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6612         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6613         return WINED3DERR_INVALIDCALL;
6614     }
6615     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6616         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6617         return WINED3DERR_INVALIDCALL;
6618     }
6619
6620     if(Swapchain->frontBuffer != Front) {
6621         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6622
6623         if(Swapchain->frontBuffer)
6624             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6625         Swapchain->frontBuffer = Front;
6626
6627         if(Swapchain->frontBuffer) {
6628             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6629         }
6630     }
6631
6632     if(Back && !Swapchain->backBuffer) {
6633         /* We need memory for the back buffer array - only one back buffer this way */
6634         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6635         if(!Swapchain->backBuffer) {
6636             ERR("Out of memory\n");
6637             return E_OUTOFMEMORY;
6638         }
6639     }
6640
6641     if(Swapchain->backBuffer[0] != Back) {
6642         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6643         ENTER_GL();
6644         if(!Swapchain->backBuffer[0]) {
6645             /* GL was told to draw to the front buffer at creation,
6646              * undo that
6647              */
6648             glDrawBuffer(GL_BACK);
6649             checkGLcall("glDrawBuffer(GL_BACK)");
6650             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6651             Swapchain->presentParms.BackBufferCount = 1;
6652         } else if (!Back) {
6653             /* That makes problems - disable for now */
6654             /* glDrawBuffer(GL_FRONT); */
6655             checkGLcall("glDrawBuffer(GL_FRONT)");
6656             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6657             Swapchain->presentParms.BackBufferCount = 0;
6658         }
6659         LEAVE_GL();
6660
6661         if(Swapchain->backBuffer[0])
6662             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6663         Swapchain->backBuffer[0] = Back;
6664
6665         if(Swapchain->backBuffer[0]) {
6666             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6667         } else {
6668             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6669         }
6670
6671     }
6672
6673     return WINED3D_OK;
6674 }
6675
6676 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6677     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6678     *ppZStencilSurface = This->depthStencilBuffer;
6679     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
6680
6681     if(*ppZStencilSurface != NULL) {
6682         /* Note inc ref on returned surface */
6683         IWineD3DSurface_AddRef(*ppZStencilSurface);
6684     }
6685     return WINED3D_OK;
6686 }
6687
6688 static void bind_fbo(IWineD3DDevice *iface) {
6689     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6690
6691     if (!This->fbo) {
6692         GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
6693         checkGLcall("glGenFramebuffersEXT()");
6694     }
6695     GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
6696     checkGLcall("glBindFramebuffer()");
6697 }
6698
6699 /* TODO: Handle stencil attachments */
6700 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
6701     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6702     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
6703
6704     This->depth_copy_state = WINED3D_DCS_NO_COPY;
6705
6706     bind_fbo(iface);
6707
6708     if (depth_stencil_impl) {
6709         GLenum texttarget, target;
6710
6711         IWineD3DSurface_PreLoad(depth_stencil);
6712         texttarget = depth_stencil_impl->glDescription.target;
6713         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
6714
6715         glBindTexture(target, depth_stencil_impl->glDescription.textureName);
6716         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6717         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6718         glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
6719         glBindTexture(target, 0);
6720
6721         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
6722         checkGLcall("glFramebufferTexture2DEXT()");
6723     } else {
6724         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
6725         checkGLcall("glFramebufferTexture2DEXT()");
6726     }
6727
6728     if (!This->render_offscreen) {
6729         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6730         checkGLcall("glBindFramebuffer()");
6731     }
6732 }
6733
6734 static void set_render_target_fbo(IWineD3DDevice *iface, IWineD3DSurface *render_target) {
6735     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6736     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
6737
6738     if (This->render_offscreen) {
6739         GLenum texttarget, target;
6740
6741         bind_fbo(iface);
6742
6743         IWineD3DSurface_PreLoad(render_target);
6744         texttarget = rtimpl->glDescription.target;
6745         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
6746
6747         glBindTexture(target, rtimpl->glDescription.textureName);
6748         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6749         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6750         glBindTexture(target, 0);
6751
6752         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texttarget, rtimpl->glDescription.textureName, 0));
6753         checkGLcall("glFramebufferTexture2DEXT()");
6754     } else {
6755         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6756         checkGLcall("glBindFramebuffer()");
6757     }
6758 }
6759
6760 /* internal static helper functions */
6761 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6762                                                 IWineD3DSurface *RenderSurface);
6763
6764 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6765     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6766     HRESULT  hr = WINED3D_OK;
6767     WINED3DVIEWPORT viewport;
6768
6769     TRACE("(%p) Swapping rendertarget\n",This);
6770     if (RenderTargetIndex > 0) {
6771         FIXME("(%p) Render targets other than the first are not supported\n",This);
6772         RenderTargetIndex = 0;
6773     }
6774
6775     /* MSDN says that null disables the render target
6776     but a device must always be associated with a render target
6777     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6778
6779     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6780     for more details
6781     */
6782     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6783         FIXME("Trying to set render target 0 to NULL\n");
6784         return WINED3DERR_INVALIDCALL;
6785     }
6786     /* TODO: replace Impl* usage with interface usage */
6787     if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
6788         FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
6789         return WINED3DERR_INVALIDCALL;
6790     }
6791     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6792      *        builds, but I think wine counts as a 'debug' build for now.
6793       ******************************/
6794     /* If we are trying to set what we already have, don't bother */
6795     if (pRenderTarget == This->renderTarget) {
6796         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6797     } else {
6798         /* Otherwise, set the render target up */
6799
6800         if (!This->sceneEnded) {
6801             IWineD3DDevice_EndScene(iface);
6802         }
6803         TRACE("clearing renderer\n");
6804         /* IWineD3DDeviceImpl_CleanRender(iface); */
6805         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6806         depending on the renter target implementation being used.
6807         A shared context implementation will share all buffers between all rendertargets (including swapchains),
6808         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6809         stencil buffer and incure an extra memory overhead */
6810         hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
6811         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
6812             set_render_target_fbo(iface, pRenderTarget);
6813         }
6814     }
6815
6816     if (SUCCEEDED(hr)) {
6817         /* Finally, reset the viewport as the MSDN states. */
6818         /* TODO: Replace impl usage */
6819         viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
6820         viewport.Width  = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
6821         viewport.X      = 0;
6822         viewport.Y      = 0;
6823         viewport.MaxZ   = 1.0f;
6824         viewport.MinZ   = 0.0f;
6825         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6826     } else {
6827         FIXME("Unknown error setting the render target\n");
6828     }
6829     This->sceneEnded = FALSE;
6830     return hr;
6831 }
6832
6833 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6834     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6835     HRESULT  hr = WINED3D_OK;
6836     IWineD3DSurface *tmp;
6837
6838     TRACE("(%p) Swapping z-buffer\n",This);
6839
6840     if (pNewZStencil == This->stencilBufferTarget) {
6841         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6842     } else {
6843         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6844         * depending on the renter target implementation being used.
6845         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6846         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6847         * stencil buffer and incure an extra memory overhead
6848          ******************************************************/
6849
6850
6851         tmp = This->stencilBufferTarget;
6852         This->stencilBufferTarget = pNewZStencil;
6853         /* should we be calling the parent or the wined3d surface? */
6854         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6855         if (NULL != tmp) IWineD3DSurface_Release(tmp);
6856         hr = WINED3D_OK;
6857         /** TODO: glEnable/glDisable on depth/stencil    depending on
6858          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
6859           **********************************************************/
6860         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
6861             set_depth_stencil_fbo(iface, pNewZStencil);
6862         }
6863     }
6864
6865     return hr;
6866 }
6867
6868
6869 #ifdef GL_VERSION_1_3
6870 /* Internal functions not in DirectX */
6871  /** TODO: move this off to the opengl context manager
6872  *(the swapchain doesn't need to know anything about offscreen rendering!)
6873   ****************************************************/
6874
6875 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
6876 {
6877     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6878
6879     TRACE("(%p), %p\n", This, swapchain);
6880
6881     if (swapchain->win != swapchain->drawable) {
6882         /* Set everything back the way it ws */
6883         swapchain->render_ctx = swapchain->glCtx;
6884         swapchain->drawable   = swapchain->win;
6885     }
6886     return WINED3D_OK;
6887 }
6888
6889 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6890 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
6891     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6892     int i;
6893     unsigned int width;
6894     unsigned int height;
6895     WINED3DFORMAT format;
6896     WINED3DSURFACE_DESC surfaceDesc;
6897     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6898     surfaceDesc.Width  = &width;
6899     surfaceDesc.Height = &height;
6900     surfaceDesc.Format = &format;
6901     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6902     *context = NULL;
6903     /* I need a get width/height function (and should do something with the format) */
6904     for (i = 0; i < CONTEXT_CACHE; ++i) {
6905         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6906         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6907         the pSurface can be set to 0 allowing it to be reused from cache **/
6908         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6909           && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6910             *context = &This->contextCache[i];
6911             break;
6912         }
6913         if (This->contextCache[i].Width == 0) {
6914             This->contextCache[i].pSurface = pSurface;
6915             This->contextCache[i].Width    = width;
6916             This->contextCache[i].Height   = height;
6917             *context = &This->contextCache[i];
6918             break;
6919         }
6920     }
6921     if (i == CONTEXT_CACHE) {
6922         int minUsage = 0x7FFFFFFF; /* MAX_INT */
6923         glContext *dropContext = 0;
6924         for (i = 0; i < CONTEXT_CACHE; i++) {
6925             if (This->contextCache[i].usedcount < minUsage) {
6926                 dropContext = &This->contextCache[i];
6927                 minUsage = This->contextCache[i].usedcount;
6928             }
6929         }
6930         /* clean up the context (this doesn't work for ATI at the moment */
6931 #if 0
6932         glXDestroyContext(swapchain->display, dropContext->context);
6933         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6934 #endif
6935         FIXME("Leak\n");
6936         dropContext->Width = 0;
6937         dropContext->pSurface = pSurface;
6938         *context = dropContext;
6939     } else {
6940         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6941           for (i = 0; i < CONTEXT_CACHE; i++) {
6942              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6943           }
6944         }
6945     }
6946     if (*context != NULL)
6947         return WINED3D_OK;
6948     else
6949         return E_OUTOFMEMORY;
6950 }
6951 #endif
6952
6953 /* Reapply the device stateblock */
6954 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
6955
6956     BOOL oldRecording;  
6957     IWineD3DStateBlockImpl *oldUpdateStateBlock;
6958
6959     /* Disable recording */
6960     oldUpdateStateBlock = This->updateStateBlock;
6961     oldRecording= This->isRecordingState;
6962     This->isRecordingState = FALSE;
6963     This->updateStateBlock = This->stateBlock;
6964
6965     /* Reapply the state block */ 
6966     IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6967
6968     /* Restore recording */
6969     This->isRecordingState = oldRecording;
6970     This->updateStateBlock = oldUpdateStateBlock;
6971 }
6972
6973 /* Set offscreen rendering. When rendering offscreen the surface will be
6974  * rendered upside down to compensate for the fact that D3D texture coordinates
6975  * are flipped compared to GL texture coordinates. The cullmode is affected by
6976  * this, so it must be updated. To update the cullmode stateblock recording has
6977  * to be temporarily disabled. The new state management code will hopefully
6978  * make this unnecessary */
6979 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
6980
6981     DWORD cullMode;
6982     BOOL oldRecording;
6983     IWineD3DStateBlockImpl *oldUpdateStateBlock;
6984
6985     /* Nothing to update, return. */
6986     if (This->render_offscreen == isTexture) return;
6987
6988     /* Disable recording */
6989     oldUpdateStateBlock = This->updateStateBlock;
6990     oldRecording= This->isRecordingState;
6991     This->isRecordingState = FALSE;
6992     This->updateStateBlock = This->stateBlock;
6993
6994     This->render_offscreen = isTexture;
6995     if (This->depth_copy_state != WINED3D_DCS_NO_COPY) {
6996         This->depth_copy_state = WINED3D_DCS_COPY;
6997     }
6998     This->last_was_rhw = FALSE;
6999     This->proj_valid = FALSE;
7000     IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
7001     IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
7002
7003     /* Restore recording */
7004     This->isRecordingState = oldRecording;
7005     This->updateStateBlock = oldUpdateStateBlock;
7006 }
7007
7008 /* Returns an array of compatible FBconfig(s).
7009  * The array must be freed with XFree. Requires ENTER_GL() */
7010
7011 static GLXFBConfig* device_find_fbconfigs(
7012     IWineD3DDeviceImpl* This,
7013     IWineD3DSwapChainImpl* implicitSwapchainImpl,
7014     IWineD3DSurface* RenderSurface) {
7015
7016     GLXFBConfig* cfgs = NULL;
7017     int nCfgs = 0;
7018     int attribs[256];
7019     int nAttribs = 0;
7020
7021     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7022     WINED3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7023     WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7024
7025     /**TODO:
7026         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off, 
7027         it StencilSurface != NULL && zBufferTarget == NULL switch it on
7028     */
7029
7030 #define PUSH1(att)        attribs[nAttribs++] = (att);
7031 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7032
7033     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7034
7035     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7036     PUSH2(GLX_X_RENDERABLE,  TRUE);
7037     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
7038     TRACE("calling makeglcfg\n");
7039     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7040     PUSH1(None);
7041     TRACE("calling chooseFGConfig\n");
7042     cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7043                              DefaultScreen(implicitSwapchainImpl->display),
7044                              attribs, &nCfgs);
7045     if (cfgs == NULL) {
7046         /* OK we didn't find the exact config, so use any reasonable match */
7047         /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
7048            why we failed. */
7049         static BOOL show_message = TRUE;
7050         if (show_message) {
7051             ERR("Failed to find exact match, finding alternative but you may "
7052                 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
7053             show_message = FALSE;
7054         }
7055         nAttribs = 0;
7056         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7057         /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
7058         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
7059         PUSH2(GLX_DOUBLEBUFFER, FALSE);
7060         TRACE("calling makeglcfg\n");
7061         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7062         PUSH1(None);
7063         cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7064                                  DefaultScreen(implicitSwapchainImpl->display),
7065                                  attribs, &nCfgs);
7066     }
7067                                                                                                                                                                       
7068     if (cfgs == NULL) {
7069         ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
7070             BackBufferFormat, debug_d3dformat(BackBufferFormat),
7071             StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7072     } else {
7073 #ifdef EXTRA_TRACES
7074         int i;
7075         for (i = 0; i < nCfgs; ++i) {
7076             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7077             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7078             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7079         }
7080         if (NULL != This->renderTarget) {
7081             glFlush();
7082             vcheckGLcall("glFlush");
7083             /** This is only useful if the old render target was a swapchain,
7084             * we need to supercede this with a function that displays
7085             * the current buffer on the screen. This is easy to do in glx1.3 but
7086             * we need to do copy-write pixels in glx 1.2.
7087             ************************************************/
7088             glXSwapBuffers(implicitSwapChainImpl->display,
7089                            implicitSwapChainImpl->drawable);
7090             printf("Hit Enter to get next frame ...\n");
7091             getchar();
7092         }
7093 #endif
7094     }
7095 #undef PUSH1
7096 #undef PUSH2
7097
7098    return cfgs;
7099 }
7100
7101 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7102 * the functionality needs splitting up so that we don't do more than we should do.
7103 * this only seems to impact performance a little.
7104  ******************************/
7105 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7106                                                IWineD3DSurface *RenderSurface) {
7107
7108     /**
7109     * Currently only active for GLX >= 1.3
7110     * for others versions we'll have to use GLXPixmaps
7111     *
7112     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7113     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7114     * so only check OpenGL version
7115     * ..........................
7116     * I don't believe that it is a problem with NVidia headers,
7117     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7118     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7119     * ATI Note:
7120     * Your application will report GLX version 1.2 on glXQueryVersion.
7121     * However, it is safe to call the GLX 1.3 functions as described below.
7122     */
7123 #if defined(GL_VERSION_1_3)
7124
7125     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7126     GLXFBConfig* cfgs = NULL;
7127     IWineD3DSwapChain     *currentSwapchain;
7128     IWineD3DSwapChainImpl *currentSwapchainImpl;
7129     IWineD3DSwapChain     *implicitSwapchain;
7130     IWineD3DSwapChainImpl *implicitSwapchainImpl;
7131     IWineD3DSwapChain     *renderSurfaceSwapchain;
7132     IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
7133
7134     /* Obtain a reference to the device implicit swapchain,
7135      * the swapchain of the current render target,
7136      * and the swapchain of the new render target.
7137      * Fallback to device implicit swapchain if the current render target doesn't have one */
7138     IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
7139     IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
7140     IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain);
7141     if (currentSwapchain == NULL)
7142         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
7143
7144     currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
7145     implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
7146     renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
7147
7148     ENTER_GL();
7149
7150     /**
7151     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7152     *  renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7153      **********************************************************************/
7154     if (renderSurfaceSwapchain != NULL) {
7155
7156         /* We also need to make sure that the lights &co are also in the context of the swapchains */
7157         /* FIXME: If the render target gets sent to the frontBuffer, should we be presenting it raw? */
7158         TRACE("making swapchain active\n");
7159         if (RenderSurface != This->renderTarget) {
7160             BOOL backbuf = FALSE;
7161             int i;
7162
7163             for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
7164                 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
7165                     backbuf = TRUE;
7166                     break;
7167                 }
7168             }
7169
7170             if (backbuf) {
7171             } else {
7172                 /* This could be flagged so that some operations work directly with the front buffer */
7173                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
7174             }
7175             if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
7176                                renderSurfaceSwapchainImpl->win,
7177                                renderSurfaceSwapchainImpl->glCtx) == False) {
7178
7179                 TRACE("Error in setting current context: context %p drawable %ld !\n",
7180                        implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
7181             }
7182             checkGLcall("glXMakeContextCurrent");
7183
7184             /* Clean up the old context */
7185             IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7186
7187             /* Reapply the stateblock, and set the device not to render to texture */
7188             device_reapply_stateblock(This);
7189             device_render_to_texture(This, FALSE);
7190         }
7191
7192     /* Offscreen rendering: PBuffers (currently disabled).
7193      * Also note that this path is never reached if FBOs are supported */
7194     } else if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER &&
7195                (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
7196
7197         /** ********************************************************************
7198         * This is a quickly hacked out implementation of offscreen textures.
7199         * It will work in most cases but there may be problems if the client
7200         * modifies the texture directly, or expects the contents of the rendertarget
7201         * to be persistent.
7202         *
7203         * There are some real speed vs compatibility issues here:
7204         *    we should really use a new context for every texture, but that eats ram.
7205         *    we should also be restoring the texture to the pbuffer but that eats CPU
7206         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7207         *    but if this means reusing the display backbuffer then we need to make sure that
7208         *    states are correctly preserved.
7209         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7210         * and gain a good performance increase at the cost of compatibility.
7211         * I would suggest that, when this is the case, a user configurable flag be made
7212         * available, allowing the user to choose the best emulated experience for them.
7213          *********************************************************************/
7214
7215         XVisualInfo *visinfo;
7216         glContext   *newContext;
7217
7218         /* Here were using a shared context model */
7219         if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7220             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7221         }
7222
7223         /* If the context doesn't exist then create a new one */
7224         /* TODO: This should really be part of findGlContext */
7225         if (NULL == newContext->context) {
7226
7227             int attribs[256];
7228             int nAttribs = 0;
7229
7230             TRACE("making new buffer\n");
7231             attribs[nAttribs++] = GLX_PBUFFER_WIDTH; 
7232             attribs[nAttribs++] = newContext->Width;
7233             attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
7234             attribs[nAttribs++] = newContext->Height;
7235             attribs[nAttribs++] = None;
7236
7237             newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
7238
7239             /** ****************************************
7240             *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7241             *they note:
7242             *   In future releases, we may provide the calls glXCreateNewContext,
7243             *   glXQueryDrawable and glXMakeContextCurrent.
7244             *    so until then we have to use glXGetVisualFromFBConfig &co..
7245             ********************************************/
7246
7247             visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
7248             if (!visinfo) {
7249                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7250             } else {
7251                 newContext->context = glXCreateContext(
7252                     implicitSwapchainImpl->display, visinfo,
7253                     implicitSwapchainImpl->glCtx, GL_TRUE);
7254
7255                 XFree(visinfo);
7256             }
7257         }
7258         if (NULL == newContext || NULL == newContext->context) {
7259             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7260         } else {
7261             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7262             if (glXMakeCurrent(implicitSwapchainImpl->display,
7263                 newContext->drawable, newContext->context) == False) {
7264
7265                 TRACE("Error in setting current context: context %p drawable %ld\n",
7266                     newContext->context, newContext->drawable);
7267             }
7268             checkGLcall("glXMakeContextCurrent");
7269
7270             /* Clean up the old context */
7271             IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7272
7273             /* Reapply stateblock, and set device to render to a texture */
7274             device_reapply_stateblock(This);
7275             device_render_to_texture(This, TRUE);
7276
7277             /* Set the current context of the swapchain to the new context */
7278             implicitSwapchainImpl->drawable   = newContext->drawable;
7279             implicitSwapchainImpl->render_ctx = newContext->context;
7280         }
7281     } else {
7282         /* Same context, but update render_offscreen and cull mode */
7283         device_render_to_texture(This, TRUE);
7284     }
7285
7286     /* Replace the render target */
7287     if (This->renderTarget != RenderSurface) {
7288         IWineD3DSurface_Release(This->renderTarget);
7289         This->renderTarget = RenderSurface;
7290         IWineD3DSurface_AddRef(RenderSurface);
7291     }
7292
7293     if (cfgs != NULL)                   XFree(cfgs);
7294     if (implicitSwapchain != NULL)       IWineD3DSwapChain_Release(implicitSwapchain);
7295     if (currentSwapchain != NULL)       IWineD3DSwapChain_Release(currentSwapchain);
7296     if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
7297     LEAVE_GL();
7298 #endif
7299     return WINED3D_OK;
7300 }
7301
7302 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7303                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7304     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7305     /* TODO: the use of Impl is deprecated. */
7306     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7307
7308     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7309
7310     /* some basic validation checks */
7311     if(This->cursorTexture) {
7312         ENTER_GL();
7313         glDeleteTextures(1, &This->cursorTexture);
7314         LEAVE_GL();
7315         This->cursorTexture = 0;
7316     }
7317
7318     if(pCursorBitmap) {
7319         /* MSDN: Cursor must be A8R8G8B8 */
7320         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7321             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7322             return WINED3DERR_INVALIDCALL;
7323         }
7324
7325         /* MSDN: Cursor must be smaller than the display mode */
7326         if(pSur->currentDesc.Width > This->ddraw_width ||
7327            pSur->currentDesc.Height > This->ddraw_height) {
7328             ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %dx%d\n", This, pSur, pSur->currentDesc.Width, pSur->currentDesc.Height, This->ddraw_width, This->ddraw_height);
7329             return WINED3DERR_INVALIDCALL;
7330         }
7331
7332         /* TODO: MSDN: Cursor sizes must be a power of 2 */
7333         /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7334          * Texture and Blitting code to draw the cursor
7335          */
7336         pSur->Flags |= SFLAG_FORCELOAD;
7337         IWineD3DSurface_PreLoad(pCursorBitmap);
7338         pSur->Flags &= ~SFLAG_FORCELOAD;
7339         /* Do not store the surface's pointer because the application may release
7340          * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7341          * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7342          */
7343         This->cursorTexture = pSur->glDescription.textureName;
7344         This->cursorWidth = pSur->currentDesc.Width;
7345         This->cursorHeight = pSur->currentDesc.Height;
7346         pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7347     }
7348
7349     This->xHotSpot = XHotSpot;
7350     This->yHotSpot = YHotSpot;
7351     return WINED3D_OK;
7352 }
7353
7354 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7355     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7356     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7357
7358     This->xScreenSpace = XScreenSpace;
7359     This->yScreenSpace = YScreenSpace;
7360
7361     return;
7362
7363 }
7364
7365 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7366     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7367     BOOL oldVisible = This->bCursorVisible;
7368     TRACE("(%p) : visible(%d)\n", This, bShow);
7369
7370     if(This->cursorTexture)
7371         This->bCursorVisible = bShow;
7372
7373     return oldVisible;
7374 }
7375
7376 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7377     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7378     TRACE("(%p) : state (%u)\n", This, This->state);
7379     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7380     switch (This->state) {
7381     case WINED3D_OK:
7382         return WINED3D_OK;
7383     case WINED3DERR_DEVICELOST:
7384         {
7385             ResourceList *resourceList  = This->resources;
7386             while (NULL != resourceList) {
7387                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7388                 return WINED3DERR_DEVICENOTRESET;
7389                 resourceList = resourceList->next;
7390             }
7391             return WINED3DERR_DEVICELOST;
7392         }
7393     case WINED3DERR_DRIVERINTERNALERROR:
7394         return WINED3DERR_DRIVERINTERNALERROR;
7395     }
7396
7397     /* Unknown state */
7398     return WINED3DERR_DRIVERINTERNALERROR;
7399 }
7400
7401
7402 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7403     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7404     /** FIXME: Resource tracking needs to be done,
7405     * The closes we can do to this is set the priorities of all managed textures low
7406     * and then reset them.
7407      ***********************************************************/
7408     FIXME("(%p) : stub\n", This);
7409     return WINED3D_OK;
7410 }
7411
7412 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7413     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
7414     if(surface->Flags & SFLAG_DIBSECTION) {
7415         /* Release the DC */
7416         SelectObject(surface->hDC, surface->dib.holdbitmap);
7417         DeleteDC(surface->hDC);
7418         /* Release the DIB section */
7419         DeleteObject(surface->dib.DIBsection);
7420         surface->dib.bitmap_data = NULL;
7421         surface->resource.allocatedMemory = NULL;
7422         surface->Flags &= ~SFLAG_DIBSECTION;
7423     }
7424     surface->currentDesc.Width = *pPresentationParameters->BackBufferWidth;
7425     surface->currentDesc.Height = *pPresentationParameters->BackBufferHeight;
7426     if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
7427         surface->pow2Width = *pPresentationParameters->BackBufferWidth;
7428         surface->pow2Height = *pPresentationParameters->BackBufferHeight;
7429     } else {
7430         surface->pow2Width = surface->pow2Height = 1;
7431         while (surface->pow2Width < *pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
7432         while (surface->pow2Height < *pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
7433     }
7434     if(surface->glDescription.textureName) {
7435         ENTER_GL();
7436         glDeleteTextures(1, &surface->glDescription.textureName);
7437         LEAVE_GL();
7438         surface->glDescription.textureName = 0;
7439     }
7440     if(surface->pow2Width != *pPresentationParameters->BackBufferWidth ||
7441        surface->pow2Height != *pPresentationParameters->BackBufferHeight) {
7442         surface->Flags |= SFLAG_NONPOW2;
7443     } else  {
7444         surface->Flags &= ~SFLAG_NONPOW2;
7445     }
7446     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
7447     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
7448 }
7449
7450 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7451     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7452     IWineD3DSwapChainImpl *swapchain;
7453     HRESULT hr;
7454     BOOL DisplayModeChanged = FALSE;
7455     WINED3DDISPLAYMODE mode;
7456     TRACE("(%p)\n", This);
7457
7458     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
7459     if(FAILED(hr)) {
7460         ERR("Failed to get the first implicit swapchain\n");
7461         return hr;
7462     }
7463
7464     /* Is it necessary to recreate the gl context? Actually every setting can be changed
7465      * on an existing gl context, so there's no real need for recreation.
7466      *
7467      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
7468      *
7469      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
7470      */
7471     TRACE("New params:\n");
7472     TRACE("BackBufferWidth = %d\n", *pPresentationParameters->BackBufferWidth);
7473     TRACE("BackBufferHeight = %d\n", *pPresentationParameters->BackBufferHeight);
7474     TRACE("BackBufferFormat = %s\n", debug_d3dformat(*pPresentationParameters->BackBufferFormat));
7475     TRACE("BackBufferCount = %d\n", *pPresentationParameters->BackBufferCount);
7476     TRACE("MultiSampleType = %d\n", *pPresentationParameters->MultiSampleType);
7477     TRACE("MultiSampleQuality = %d\n", *pPresentationParameters->MultiSampleQuality);
7478     TRACE("SwapEffect = %d\n", *pPresentationParameters->SwapEffect);
7479     TRACE("hDeviceWindow = %p\n", *pPresentationParameters->hDeviceWindow);
7480     TRACE("Windowed = %s\n", *pPresentationParameters->Windowed ? "true" : "false");
7481     TRACE("EnableAutoDepthStencil = %s\n", *pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
7482     TRACE("Flags = %08x\n", *pPresentationParameters->Flags);
7483     TRACE("FullScreen_RefreshRateInHz = %d\n", *pPresentationParameters->FullScreen_RefreshRateInHz);
7484     TRACE("PresentationInterval = %d\n", *pPresentationParameters->PresentationInterval);
7485
7486     /* No special treatment of these parameters. Just store them */
7487     swapchain->presentParms.SwapEffect = *pPresentationParameters->SwapEffect;
7488     swapchain->presentParms.Flags = *pPresentationParameters->Flags;
7489     swapchain->presentParms.PresentationInterval = *pPresentationParameters->PresentationInterval;
7490     swapchain->presentParms.FullScreen_RefreshRateInHz = *pPresentationParameters->FullScreen_RefreshRateInHz;
7491
7492     /* What to do about these? */
7493     if(*pPresentationParameters->BackBufferCount != 0 &&
7494         *pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
7495         ERR("Cannot change the back buffer count yet\n");
7496     }
7497     if(*pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
7498         *pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
7499         ERR("Cannot change the back buffer format yet\n");
7500     }
7501     if(*pPresentationParameters->hDeviceWindow != NULL &&
7502         *pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
7503         ERR("Cannot change the device window yet\n");
7504     }
7505     if(*pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
7506         ERR("What do do about a changed auto depth stencil parameter?\n");
7507     }
7508
7509     if(*pPresentationParameters->Windowed) {
7510         mode.Width = swapchain->orig_width;
7511         mode.Height = swapchain->orig_height;
7512         mode.RefreshRate = 0;
7513         mode.Format = swapchain->presentParms.BackBufferFormat;
7514     } else {
7515         mode.Width = *pPresentationParameters->BackBufferWidth;
7516         mode.Height = *pPresentationParameters->BackBufferHeight;
7517         mode.RefreshRate = *pPresentationParameters->FullScreen_RefreshRateInHz;
7518         mode.Format = swapchain->presentParms.BackBufferFormat;
7519     }
7520
7521     /* Should Width == 800 && Height == 0 set 800x600? */
7522     if(*pPresentationParameters->BackBufferWidth != 0 && *pPresentationParameters->BackBufferHeight != 0 &&
7523        (*pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
7524         *pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
7525     {
7526         WINED3DVIEWPORT vp;
7527         int i;
7528
7529         vp.X = 0;
7530         vp.Y = 0;
7531         vp.Width = *pPresentationParameters->BackBufferWidth;
7532         vp.Height = *pPresentationParameters->BackBufferHeight;
7533         vp.MinZ = 0;
7534         vp.MaxZ = 1;
7535
7536         if(!*pPresentationParameters->Windowed) {
7537             DisplayModeChanged = TRUE;
7538         }
7539         swapchain->presentParms.BackBufferWidth = *pPresentationParameters->BackBufferWidth;
7540         swapchain->presentParms.BackBufferHeight = *pPresentationParameters->BackBufferHeight;
7541
7542         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
7543         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
7544             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
7545         }
7546
7547         /* Now set the new viewport */
7548         IWineD3DDevice_SetViewport(iface, &vp);
7549     }
7550
7551     if((*pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
7552        (swapchain->presentParms.Windowed && !*pPresentationParameters->Windowed) ||
7553         DisplayModeChanged) {
7554         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
7555     }
7556
7557     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
7558     return WINED3D_OK;
7559 }
7560
7561 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7562     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7563     /** FIXME: always true at the moment **/
7564     if(!bEnableDialogs) {
7565         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7566     }
7567     return WINED3D_OK;
7568 }
7569
7570
7571 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7572     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7573     TRACE("(%p) : pParameters %p\n", This, pParameters);
7574
7575     *pParameters = This->createParms;
7576     return WINED3D_OK;
7577 }
7578
7579 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7580     IWineD3DSwapChain *swapchain;
7581     HRESULT hrc = WINED3D_OK;
7582
7583     TRACE("Relaying  to swapchain\n");
7584
7585     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7586         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7587         IWineD3DSwapChain_Release(swapchain);
7588     }
7589     return;
7590 }
7591
7592 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7593     IWineD3DSwapChain *swapchain;
7594     HRESULT hrc = WINED3D_OK;
7595
7596     TRACE("Relaying  to swapchain\n");
7597
7598     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7599         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7600         IWineD3DSwapChain_Release(swapchain);
7601     }
7602     return;
7603 }
7604
7605
7606 /** ********************************************************
7607 *   Notification functions
7608 ** ********************************************************/
7609 /** This function must be called in the release of a resource when ref == 0,
7610 * the contents of resource must still be correct,
7611 * any handels to other resource held by the caller must be closed
7612 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7613  *****************************************************/
7614 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7615     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7616     ResourceList* resourceList;
7617
7618     TRACE("(%p) : resource %p\n", This, resource);
7619 #if 0
7620     EnterCriticalSection(&resourceStoreCriticalSection);
7621 #endif
7622     /* add a new texture to the frot of the linked list */
7623     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7624     resourceList->resource = resource;
7625
7626     /* Get the old head */
7627     resourceList->next = This->resources;
7628
7629     This->resources = resourceList;
7630     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7631
7632 #if 0
7633     LeaveCriticalSection(&resourceStoreCriticalSection);
7634 #endif
7635     return;
7636 }
7637
7638 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7639     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7640     ResourceList* resourceList = NULL;
7641     ResourceList* previousResourceList = NULL;
7642     
7643     TRACE("(%p) : resource %p\n", This, resource);
7644
7645 #if 0
7646     EnterCriticalSection(&resourceStoreCriticalSection);
7647 #endif
7648     resourceList = This->resources;
7649
7650     while (resourceList != NULL) {
7651         if(resourceList->resource == resource) break;
7652         previousResourceList = resourceList;
7653         resourceList = resourceList->next;
7654     }
7655
7656     if (resourceList == NULL) {
7657         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7658 #if 0
7659         LeaveCriticalSection(&resourceStoreCriticalSection);
7660 #endif
7661         return;
7662     } else {
7663             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7664     }
7665     /* make sure we don't leave a hole in the list */
7666     if (previousResourceList != NULL) {
7667         previousResourceList->next = resourceList->next;
7668     } else {
7669         This->resources = resourceList->next;
7670     }
7671
7672 #if 0
7673     LeaveCriticalSection(&resourceStoreCriticalSection);
7674 #endif
7675     return;
7676 }
7677
7678
7679 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7680     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7681     int counter;
7682
7683     TRACE("(%p) : resource %p\n", This, resource);
7684     switch(IWineD3DResource_GetType(resource)){
7685         case WINED3DRTYPE_SURFACE:
7686         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
7687         break;
7688         case WINED3DRTYPE_TEXTURE:
7689         case WINED3DRTYPE_CUBETEXTURE:
7690         case WINED3DRTYPE_VOLUMETEXTURE:
7691                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7692                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7693                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7694                         This->stateBlock->textures[counter] = NULL;
7695                     }
7696                     if (This->updateStateBlock != This->stateBlock ){
7697                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7698                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7699                             This->updateStateBlock->textures[counter] = NULL;
7700                         }
7701                     }
7702                 }
7703         break;
7704         case WINED3DRTYPE_VOLUME:
7705         /* TODO: nothing really? */
7706         break;
7707         case WINED3DRTYPE_VERTEXBUFFER:
7708         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7709         {
7710             int streamNumber;
7711             TRACE("Cleaning up stream pointers\n");
7712
7713             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7714                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7715                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7716                 */
7717                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7718                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7719                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7720                         This->updateStateBlock->streamSource[streamNumber] = 0;
7721                         /* Set changed flag? */
7722                     }
7723                 }
7724                 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) */
7725                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7726                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7727                         This->stateBlock->streamSource[streamNumber] = 0;
7728                     }
7729                 }
7730 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7731                  else { /* This shouldn't happen */
7732                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7733                 }
7734 #endif
7735
7736             }
7737         }
7738         break;
7739         case WINED3DRTYPE_INDEXBUFFER:
7740         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7741         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7742             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7743                 This->updateStateBlock->pIndexData =  NULL;
7744             }
7745         }
7746         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7747             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7748                 This->stateBlock->pIndexData =  NULL;
7749             }
7750         }
7751
7752         break;
7753         default:
7754         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7755         break;
7756     }
7757
7758
7759     /* Remove the resoruce from the resourceStore */
7760     IWineD3DDeviceImpl_RemoveResource(iface, resource);
7761
7762     TRACE("Resource released\n");
7763
7764 }
7765
7766 /**********************************************************
7767  * IWineD3DDevice VTbl follows
7768  **********************************************************/
7769
7770 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7771 {
7772     /*** IUnknown methods ***/
7773     IWineD3DDeviceImpl_QueryInterface,
7774     IWineD3DDeviceImpl_AddRef,
7775     IWineD3DDeviceImpl_Release,
7776     /*** IWineD3DDevice methods ***/
7777     IWineD3DDeviceImpl_GetParent,
7778     /*** Creation methods**/
7779     IWineD3DDeviceImpl_CreateVertexBuffer,
7780     IWineD3DDeviceImpl_CreateIndexBuffer,
7781     IWineD3DDeviceImpl_CreateStateBlock,
7782     IWineD3DDeviceImpl_CreateSurface,
7783     IWineD3DDeviceImpl_CreateTexture,
7784     IWineD3DDeviceImpl_CreateVolumeTexture,
7785     IWineD3DDeviceImpl_CreateVolume,
7786     IWineD3DDeviceImpl_CreateCubeTexture,
7787     IWineD3DDeviceImpl_CreateQuery,
7788     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7789     IWineD3DDeviceImpl_CreateVertexDeclaration,
7790     IWineD3DDeviceImpl_CreateVertexShader,
7791     IWineD3DDeviceImpl_CreatePixelShader,
7792     IWineD3DDeviceImpl_CreatePalette,
7793     /*** Odd functions **/
7794     IWineD3DDeviceImpl_Init3D,
7795     IWineD3DDeviceImpl_Uninit3D,
7796     IWineD3DDeviceImpl_SetFullscreen,
7797     IWineD3DDeviceImpl_EnumDisplayModes,
7798     IWineD3DDeviceImpl_EvictManagedResources,
7799     IWineD3DDeviceImpl_GetAvailableTextureMem,
7800     IWineD3DDeviceImpl_GetBackBuffer,
7801     IWineD3DDeviceImpl_GetCreationParameters,
7802     IWineD3DDeviceImpl_GetDeviceCaps,
7803     IWineD3DDeviceImpl_GetDirect3D,
7804     IWineD3DDeviceImpl_GetDisplayMode,
7805     IWineD3DDeviceImpl_SetDisplayMode,
7806     IWineD3DDeviceImpl_GetHWND,
7807     IWineD3DDeviceImpl_SetHWND,
7808     IWineD3DDeviceImpl_GetNumberOfSwapChains,
7809     IWineD3DDeviceImpl_GetRasterStatus,
7810     IWineD3DDeviceImpl_GetSwapChain,
7811     IWineD3DDeviceImpl_Reset,
7812     IWineD3DDeviceImpl_SetDialogBoxMode,
7813     IWineD3DDeviceImpl_SetCursorProperties,
7814     IWineD3DDeviceImpl_SetCursorPosition,
7815     IWineD3DDeviceImpl_ShowCursor,
7816     IWineD3DDeviceImpl_TestCooperativeLevel,
7817     /*** Getters and setters **/
7818     IWineD3DDeviceImpl_SetClipPlane,
7819     IWineD3DDeviceImpl_GetClipPlane,
7820     IWineD3DDeviceImpl_SetClipStatus,
7821     IWineD3DDeviceImpl_GetClipStatus,
7822     IWineD3DDeviceImpl_SetCurrentTexturePalette,
7823     IWineD3DDeviceImpl_GetCurrentTexturePalette,
7824     IWineD3DDeviceImpl_SetDepthStencilSurface,
7825     IWineD3DDeviceImpl_GetDepthStencilSurface,
7826     IWineD3DDeviceImpl_SetFVF,
7827     IWineD3DDeviceImpl_GetFVF,
7828     IWineD3DDeviceImpl_SetGammaRamp,
7829     IWineD3DDeviceImpl_GetGammaRamp,
7830     IWineD3DDeviceImpl_SetIndices,
7831     IWineD3DDeviceImpl_GetIndices,
7832     IWineD3DDeviceImpl_SetLight,
7833     IWineD3DDeviceImpl_GetLight,
7834     IWineD3DDeviceImpl_SetLightEnable,
7835     IWineD3DDeviceImpl_GetLightEnable,
7836     IWineD3DDeviceImpl_SetMaterial,
7837     IWineD3DDeviceImpl_GetMaterial,
7838     IWineD3DDeviceImpl_SetNPatchMode,
7839     IWineD3DDeviceImpl_GetNPatchMode,
7840     IWineD3DDeviceImpl_SetPaletteEntries,
7841     IWineD3DDeviceImpl_GetPaletteEntries,
7842     IWineD3DDeviceImpl_SetPixelShader,
7843     IWineD3DDeviceImpl_GetPixelShader,
7844     IWineD3DDeviceImpl_SetPixelShaderConstantB,
7845     IWineD3DDeviceImpl_GetPixelShaderConstantB,
7846     IWineD3DDeviceImpl_SetPixelShaderConstantI,
7847     IWineD3DDeviceImpl_GetPixelShaderConstantI,
7848     IWineD3DDeviceImpl_SetPixelShaderConstantF,
7849     IWineD3DDeviceImpl_GetPixelShaderConstantF,
7850     IWineD3DDeviceImpl_SetRenderState,
7851     IWineD3DDeviceImpl_GetRenderState,
7852     IWineD3DDeviceImpl_SetRenderTarget,
7853     IWineD3DDeviceImpl_GetRenderTarget,
7854     IWineD3DDeviceImpl_SetFrontBackBuffers,
7855     IWineD3DDeviceImpl_SetSamplerState,
7856     IWineD3DDeviceImpl_GetSamplerState,
7857     IWineD3DDeviceImpl_SetScissorRect,
7858     IWineD3DDeviceImpl_GetScissorRect,
7859     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7860     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7861     IWineD3DDeviceImpl_SetStreamSource,
7862     IWineD3DDeviceImpl_GetStreamSource,
7863     IWineD3DDeviceImpl_SetStreamSourceFreq,
7864     IWineD3DDeviceImpl_GetStreamSourceFreq,
7865     IWineD3DDeviceImpl_SetTexture,
7866     IWineD3DDeviceImpl_GetTexture,
7867     IWineD3DDeviceImpl_SetTextureStageState,
7868     IWineD3DDeviceImpl_GetTextureStageState,
7869     IWineD3DDeviceImpl_SetTransform,
7870     IWineD3DDeviceImpl_GetTransform,
7871     IWineD3DDeviceImpl_SetVertexDeclaration,
7872     IWineD3DDeviceImpl_GetVertexDeclaration,
7873     IWineD3DDeviceImpl_SetVertexShader,
7874     IWineD3DDeviceImpl_GetVertexShader,
7875     IWineD3DDeviceImpl_SetVertexShaderConstantB,
7876     IWineD3DDeviceImpl_GetVertexShaderConstantB,
7877     IWineD3DDeviceImpl_SetVertexShaderConstantI,
7878     IWineD3DDeviceImpl_GetVertexShaderConstantI,
7879     IWineD3DDeviceImpl_SetVertexShaderConstantF,
7880     IWineD3DDeviceImpl_GetVertexShaderConstantF,
7881     IWineD3DDeviceImpl_SetViewport,
7882     IWineD3DDeviceImpl_GetViewport,
7883     IWineD3DDeviceImpl_MultiplyTransform,
7884     IWineD3DDeviceImpl_ValidateDevice,
7885     IWineD3DDeviceImpl_ProcessVertices,
7886     /*** State block ***/
7887     IWineD3DDeviceImpl_BeginStateBlock,
7888     IWineD3DDeviceImpl_EndStateBlock,
7889     /*** Scene management ***/
7890     IWineD3DDeviceImpl_BeginScene,
7891     IWineD3DDeviceImpl_EndScene,
7892     IWineD3DDeviceImpl_Present,
7893     IWineD3DDeviceImpl_Clear,
7894     /*** Drawing ***/
7895     IWineD3DDeviceImpl_DrawPrimitive,
7896     IWineD3DDeviceImpl_DrawIndexedPrimitive,
7897     IWineD3DDeviceImpl_DrawPrimitiveUP,
7898     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7899     IWineD3DDeviceImpl_DrawPrimitiveStrided,
7900     IWineD3DDeviceImpl_DrawRectPatch,
7901     IWineD3DDeviceImpl_DrawTriPatch,
7902     IWineD3DDeviceImpl_DeletePatch,
7903     IWineD3DDeviceImpl_ColorFill,
7904     IWineD3DDeviceImpl_UpdateTexture,
7905     IWineD3DDeviceImpl_UpdateSurface,
7906     IWineD3DDeviceImpl_StretchRect,
7907     IWineD3DDeviceImpl_GetRenderTargetData,
7908     IWineD3DDeviceImpl_GetFrontBufferData,
7909     /*** Internal use IWineD3DDevice methods ***/
7910     IWineD3DDeviceImpl_SetupTextureStates,
7911     /*** object tracking ***/
7912     IWineD3DDeviceImpl_ResourceReleased
7913 };
7914
7915
7916 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7917     WINED3DRS_ALPHABLENDENABLE   ,
7918     WINED3DRS_ALPHAFUNC          ,
7919     WINED3DRS_ALPHAREF           ,
7920     WINED3DRS_ALPHATESTENABLE    ,
7921     WINED3DRS_BLENDOP            ,
7922     WINED3DRS_COLORWRITEENABLE   ,
7923     WINED3DRS_DESTBLEND          ,
7924     WINED3DRS_DITHERENABLE       ,
7925     WINED3DRS_FILLMODE           ,
7926     WINED3DRS_FOGDENSITY         ,
7927     WINED3DRS_FOGEND             ,
7928     WINED3DRS_FOGSTART           ,
7929     WINED3DRS_LASTPIXEL          ,
7930     WINED3DRS_SHADEMODE          ,
7931     WINED3DRS_SRCBLEND           ,
7932     WINED3DRS_STENCILENABLE      ,
7933     WINED3DRS_STENCILFAIL        ,
7934     WINED3DRS_STENCILFUNC        ,
7935     WINED3DRS_STENCILMASK        ,
7936     WINED3DRS_STENCILPASS        ,
7937     WINED3DRS_STENCILREF         ,
7938     WINED3DRS_STENCILWRITEMASK   ,
7939     WINED3DRS_STENCILZFAIL       ,
7940     WINED3DRS_TEXTUREFACTOR      ,
7941     WINED3DRS_WRAP0              ,
7942     WINED3DRS_WRAP1              ,
7943     WINED3DRS_WRAP2              ,
7944     WINED3DRS_WRAP3              ,
7945     WINED3DRS_WRAP4              ,
7946     WINED3DRS_WRAP5              ,
7947     WINED3DRS_WRAP6              ,
7948     WINED3DRS_WRAP7              ,
7949     WINED3DRS_ZENABLE            ,
7950     WINED3DRS_ZFUNC              ,
7951     WINED3DRS_ZWRITEENABLE
7952 };
7953
7954 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7955     WINED3DTSS_ADDRESSW              ,
7956     WINED3DTSS_ALPHAARG0             ,
7957     WINED3DTSS_ALPHAARG1             ,
7958     WINED3DTSS_ALPHAARG2             ,
7959     WINED3DTSS_ALPHAOP               ,
7960     WINED3DTSS_BUMPENVLOFFSET        ,
7961     WINED3DTSS_BUMPENVLSCALE         ,
7962     WINED3DTSS_BUMPENVMAT00          ,
7963     WINED3DTSS_BUMPENVMAT01          ,
7964     WINED3DTSS_BUMPENVMAT10          ,
7965     WINED3DTSS_BUMPENVMAT11          ,
7966     WINED3DTSS_COLORARG0             ,
7967     WINED3DTSS_COLORARG1             ,
7968     WINED3DTSS_COLORARG2             ,
7969     WINED3DTSS_COLOROP               ,
7970     WINED3DTSS_RESULTARG             ,
7971     WINED3DTSS_TEXCOORDINDEX         ,
7972     WINED3DTSS_TEXTURETRANSFORMFLAGS
7973 };
7974
7975 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7976     WINED3DSAMP_ADDRESSU         ,
7977     WINED3DSAMP_ADDRESSV         ,
7978     WINED3DSAMP_ADDRESSW         ,
7979     WINED3DSAMP_BORDERCOLOR      ,
7980     WINED3DSAMP_MAGFILTER        ,
7981     WINED3DSAMP_MINFILTER        ,
7982     WINED3DSAMP_MIPFILTER        ,
7983     WINED3DSAMP_MIPMAPLODBIAS    ,
7984     WINED3DSAMP_MAXMIPLEVEL      ,
7985     WINED3DSAMP_MAXANISOTROPY    ,
7986     WINED3DSAMP_SRGBTEXTURE      ,
7987     WINED3DSAMP_ELEMENTINDEX
7988 };
7989
7990 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7991     WINED3DRS_AMBIENT                       ,
7992     WINED3DRS_AMBIENTMATERIALSOURCE         ,
7993     WINED3DRS_CLIPPING                      ,
7994     WINED3DRS_CLIPPLANEENABLE               ,
7995     WINED3DRS_COLORVERTEX                   ,
7996     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
7997     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
7998     WINED3DRS_FOGDENSITY                    ,
7999     WINED3DRS_FOGEND                        ,
8000     WINED3DRS_FOGSTART                      ,
8001     WINED3DRS_FOGTABLEMODE                  ,
8002     WINED3DRS_FOGVERTEXMODE                 ,
8003     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
8004     WINED3DRS_LIGHTING                      ,
8005     WINED3DRS_LOCALVIEWER                   ,
8006     WINED3DRS_MULTISAMPLEANTIALIAS          ,
8007     WINED3DRS_MULTISAMPLEMASK               ,
8008     WINED3DRS_NORMALIZENORMALS              ,
8009     WINED3DRS_PATCHEDGESTYLE                ,
8010     WINED3DRS_POINTSCALE_A                  ,
8011     WINED3DRS_POINTSCALE_B                  ,
8012     WINED3DRS_POINTSCALE_C                  ,
8013     WINED3DRS_POINTSCALEENABLE              ,
8014     WINED3DRS_POINTSIZE                     ,
8015     WINED3DRS_POINTSIZE_MAX                 ,
8016     WINED3DRS_POINTSIZE_MIN                 ,
8017     WINED3DRS_POINTSPRITEENABLE             ,
8018     WINED3DRS_RANGEFOGENABLE                ,
8019     WINED3DRS_SPECULARMATERIALSOURCE        ,
8020     WINED3DRS_TWEENFACTOR                   ,
8021     WINED3DRS_VERTEXBLEND
8022 };
8023
8024 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8025     WINED3DTSS_TEXCOORDINDEX         ,
8026     WINED3DTSS_TEXTURETRANSFORMFLAGS
8027 };
8028
8029 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8030     WINED3DSAMP_DMAPOFFSET
8031 };