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