wined3d: Move WINED3DTSS_TEXCOORDINDEX to the state table.
[wine] / dlls / wined3d / device.c
1 /*
2  * IWineD3DDevice implementation
3  *
4  * Copyright 2002 Lionel Ulmer
5  * Copyright 2002-2005 Jason Edmeades
6  * Copyright 2003-2004 Raphael Junqueira
7  * Copyright 2004 Christian Costa
8  * Copyright 2005 Oliver Stieber
9  * Copyright 2006 Stefan Dösinger for CodeWeavers
10  * Copyright 2006 Henri Verbeet
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include <stdio.h>
29 #ifdef HAVE_FLOAT_H
30 # include <float.h>
31 #endif
32 #include "wined3d_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
37
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light = {
40
41     WINED3DLIGHT_DIRECTIONAL, /* Type */
42     { 1.0, 1.0, 1.0, 0.0 },   /* Diffuse r,g,b,a */
43     { 0.0, 0.0, 0.0, 0.0 },   /* Specular r,g,b,a */
44     { 0.0, 0.0, 0.0, 0.0 },   /* Ambient r,g,b,a, */
45     { 0.0, 0.0, 0.0 },        /* Position x,y,z */
46     { 0.0, 0.0, 1.0 },        /* Direction x,y,z */
47     0.0,                      /* Range */
48     0.0,                      /* Falloff */
49     0.0, 0.0, 0.0,            /* Attenuation 0,1,2 */
50     0.0,                      /* Theta */
51     0.0                       /* Phi */
52 };
53
54 /* x11drv GDI escapes */
55 #define X11DRV_ESCAPE 6789
56 enum x11drv_escape_codes
57 {
58     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
59     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
60     X11DRV_GET_FONT,      /* get current X font for a DC */
61 };
62
63 /* retrieve the X display to use on a given DC */
64 inline static Display *get_display( HDC hdc )
65 {
66     Display *display;
67     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
68
69     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
70                     sizeof(display), (LPSTR)&display )) display = NULL;
71     return display;
72 }
73
74 /* allocate one pbuffer per surface */
75 BOOL pbuffer_per_surface = FALSE;
76
77 /* static function declarations */
78 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
79
80 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
81
82 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil);
83
84 /* helper macros */
85 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
86
87 #define D3DCREATEOBJECTINSTANCE(object, type) { \
88     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
89     D3DMEMCHECK(object, pp##type); \
90     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
91     object->wineD3DDevice = This; \
92     object->parent       = parent; \
93     object->ref          = 1; \
94     *pp##type = (IWineD3D##type *) object; \
95 }
96
97 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
98     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
99     D3DMEMCHECK(object, pp##type); \
100     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
101     object->parent       = parent; \
102     object->ref          = 1; \
103     object->baseShader.device = (IWineD3DDevice*) This; \
104     *pp##type = (IWineD3D##type *) object; \
105 }
106
107 #define  D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
108     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
109     D3DMEMCHECK(object, pp##type); \
110     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
111     object->resource.wineD3DDevice   = This; \
112     object->resource.parent          = parent; \
113     object->resource.resourceType    = d3dtype; \
114     object->resource.ref             = 1; \
115     object->resource.pool            = Pool; \
116     object->resource.format          = Format; \
117     object->resource.usage           = Usage; \
118     object->resource.size            = _size; \
119     /* Check that we have enough video ram left */ \
120     if (Pool == WINED3DPOOL_DEFAULT) { \
121         if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
122             WARN("Out of 'bogus' video memory\n"); \
123             HeapFree(GetProcessHeap(), 0, object); \
124             *pp##type = NULL; \
125             return WINED3DERR_OUTOFVIDEOMEMORY; \
126         } \
127         globalChangeGlRam(_size); \
128     } \
129     object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
130     if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
131         FIXME("Out of memory!\n"); \
132         HeapFree(GetProcessHeap(), 0, object); \
133         *pp##type = NULL; \
134         return WINED3DERR_OUTOFVIDEOMEMORY; \
135     } \
136     *pp##type = (IWineD3D##type *) object; \
137     IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
138     TRACE("(%p) : Created resource %p\n", This, object); \
139 }
140
141 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
142     _basetexture.levels     = Levels; \
143     _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
144     _basetexture.LOD        = 0; \
145     _basetexture.dirty      = TRUE; \
146 }
147
148 /**********************************************************
149  * Global variable / Constants follow
150  **********************************************************/
151 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
152
153 /**********************************************************
154  * Utility functions follow
155  **********************************************************/
156 /* Convert the WINED3DLIGHT properties into equivalent gl lights */
157 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
158
159     float quad_att;
160     float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
161     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
162
163     /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
164     glMatrixMode(GL_MODELVIEW);
165     glPushMatrix();
166     glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
167
168     /* Diffuse: */
169     colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
170     colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
171     colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
172     colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
173     glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
174     checkGLcall("glLightfv");
175
176     /* Specular */
177     colRGBA[0] = lightInfo->OriginalParms.Specular.r;
178     colRGBA[1] = lightInfo->OriginalParms.Specular.g;
179     colRGBA[2] = lightInfo->OriginalParms.Specular.b;
180     colRGBA[3] = lightInfo->OriginalParms.Specular.a;
181     glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
182     checkGLcall("glLightfv");
183
184     /* Ambient */
185     colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
186     colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
187     colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
188     colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
189     glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
190     checkGLcall("glLightfv");
191
192     /* Attenuation - Are these right? guessing... */
193     glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
194     checkGLcall("glLightf");
195     glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
196     checkGLcall("glLightf");
197
198     if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
199         quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
200     } else {
201         quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
202     }
203
204     if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
205     glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
206     checkGLcall("glLightf");
207
208     switch (lightInfo->OriginalParms.Type) {
209     case WINED3DLIGHT_POINT:
210         /* Position */
211         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
212         checkGLcall("glLightfv");
213         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
214         checkGLcall("glLightf");
215         /* FIXME: Range */
216         break;
217
218     case WINED3DLIGHT_SPOT:
219         /* Position */
220         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
221         checkGLcall("glLightfv");
222         /* Direction */
223         glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
224         checkGLcall("glLightfv");
225         glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
226         checkGLcall("glLightf");
227         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
228         checkGLcall("glLightf");
229         /* FIXME: Range */
230         break;
231
232     case WINED3DLIGHT_DIRECTIONAL:
233         /* Direction */
234         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
235         checkGLcall("glLightfv");
236         glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
237         checkGLcall("glLightf");
238         glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
239         checkGLcall("glLightf");
240         break;
241
242     default:
243         FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
244     }
245
246     /* Restore the modelview matrix */
247     glPopMatrix();
248 }
249
250 /**********************************************************
251  * GLSL helper functions follow
252  **********************************************************/
253
254 /** Attach a GLSL pixel or vertex shader object to the shader program */
255 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
256
257     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
258     GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
259     if (This->stateBlock->glsl_program && shaderObj != 0) {
260         TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
261         GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
262         checkGLcall("glAttachObjectARB");
263     }
264 }
265
266 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
267  * It sets the programId on the current StateBlock (because it should be called
268  * inside of the DrawPrimitive() part of the render loop).
269  *
270  * If a program for the given combination does not exist, create one, and store
271  * the program in the list.  If it creates a program, it will link the given 
272  * objects, too.
273  * 
274  * We keep the shader programs around on a list because linking
275  * shader objects together is an expensive operation.  It's much
276  * faster to loop through a list of pre-compiled & linked programs
277  * each time that the application sets a new pixel or vertex shader
278  * than it is to re-link them together at that time.
279  *
280  * The list will be deleted in IWineD3DDevice::Release().
281  */
282 void set_glsl_shader_program(IWineD3DDevice *iface) {
283
284     IWineD3DDeviceImpl *This               = (IWineD3DDeviceImpl *)iface;
285     IWineD3DPixelShader  *pshader          = This->stateBlock->pixelShader;
286     IWineD3DVertexShader *vshader          = This->stateBlock->vertexShader;
287     struct glsl_shader_prog_link *curLink  = NULL;
288     struct glsl_shader_prog_link *newLink  = NULL;
289     struct list *ptr                       = NULL;
290     GLhandleARB programId                  = 0;
291     int i;
292     char glsl_name[8];
293     
294     ptr = list_head( &This->glsl_shader_progs );
295     while (ptr) {
296         /* At least one program exists - see if it matches our ps/vs combination */
297         curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
298         if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
299             /* Existing Program found, use it */
300             TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n", 
301                    curLink->programId);
302             This->stateBlock->glsl_program = curLink;
303             return;
304         }
305         /* This isn't the entry we need - try the next one */
306         ptr = list_next( &This->glsl_shader_progs, ptr );
307     }
308
309     /* If we get to this point, then no matching program exists, so we create one */
310     programId = GL_EXTCALL(glCreateProgramObjectARB());
311     TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
312
313     /* Allocate a new link for the list of programs */
314     newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
315     newLink->programId    = programId;
316     This->stateBlock->glsl_program = newLink;
317    
318     /* Attach GLSL vshader */ 
319     if (NULL != vshader && This->vs_selected_mode == SHADER_GLSL) {
320         int i;
321         int max_attribs = 16;   /* TODO: Will this always be the case? It is at the moment... */
322         char tmp_name[10];
323     
324         TRACE("Attaching vertex shader to GLSL program\n");    
325         attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
326         
327         /* Bind vertex attributes to a corresponding index number to match
328          * the same index numbers as ARB_vertex_programs (makes loading
329          * vertex attributes simpler).  With this method, we can use the
330          * exact same code to load the attributes later for both ARB and 
331          * GLSL shaders.
332          * 
333          * We have to do this here because we need to know the Program ID
334          * in order to make the bindings work, and it has to be done prior
335          * to linking the GLSL program. */
336         for (i = 0; i < max_attribs; ++i) {
337              snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
338              GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
339         }
340         checkGLcall("glBindAttribLocationARB");
341         newLink->vertexShader = vshader;
342     }
343     
344     /* Attach GLSL pshader */
345     if (NULL != pshader && This->ps_selected_mode == SHADER_GLSL) {
346         TRACE("Attaching pixel shader to GLSL program\n");
347         attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
348         newLink->pixelShader = pshader;
349     }    
350
351     /* Link the program */
352     TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId);
353     GL_EXTCALL(glLinkProgramARB(programId));
354     print_glsl_info_log(&GLINFO_LOCATION, programId);
355     list_add_head( &This->glsl_shader_progs, &newLink->entry);
356
357     newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF));
358     for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
359         snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i);
360         newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
361     }
362     newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF));
363     for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
364         snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i);
365         newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
366     }
367
368     return;
369 }
370
371 /** Detach the GLSL pixel or vertex shader object from the shader program */
372 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
373
374     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
375
376     if (shaderObj != 0 && programId != 0) {
377         TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
378         GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
379         checkGLcall("glDetachObjectARB");
380     }
381 }
382
383 /** Delete a GLSL shader program */
384 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
385
386     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
387     
388     if (obj != 0) {
389         TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
390         GL_EXTCALL(glDeleteObjectARB(obj));
391         checkGLcall("glDeleteObjectARB");
392     }
393 }
394
395 /** Delete the list of linked programs this shader is associated with.
396  * Also at this point, check to see if there are any objects left attached
397  * to each GLSL program.  If not, delete the GLSL program object.
398  * This will be run when a device is released. */
399 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
400     
401     struct list *ptr                       = NULL;
402     struct glsl_shader_prog_link *curLink  = NULL;
403     IWineD3DDeviceImpl *This               = (IWineD3DDeviceImpl *)iface;
404     
405     int numAttached = 0;
406     int i;
407     GLhandleARB objList[2];   /* There should never be more than 2 objects attached 
408                                  (one pixel shader and one vertex shader at most) */
409     
410     ptr = list_head( &This->glsl_shader_progs );
411     while (ptr) {
412         /* First, get the current item,
413          * save the link to the next pointer, 
414          * detach and delete shader objects,
415          * then de-allocate the list item's memory */
416         curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
417         ptr = list_next( &This->glsl_shader_progs, ptr );
418
419         /* See if this object is still attached to the program - it may have been detached already */
420         GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
421         TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
422         for (i = 0; i < numAttached; i++) {
423             detach_glsl_shader(iface, objList[i], curLink->programId);
424         }
425         
426         delete_glsl_shader_program(iface, curLink->programId);
427
428         /* Free the uniform locations */
429         HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
430         HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
431
432         /* Free the memory for this list item */    
433         HeapFree(GetProcessHeap(), 0, curLink);
434     }
435 }
436
437
438 /* Apply the current values to the specified texture stage */
439 static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
440     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
441     float col[4];
442
443     union {
444         float f;
445         DWORD d;
446     } tmpvalue;
447
448     /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
449     clamping, MIPLOD, etc. This will work for up to 16 samplers.
450     */
451    
452     if (Sampler >= GL_LIMITS(sampler_stages)) {
453         FIXME("Trying to set the state of more samplers %d than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
454         return;
455     }
456     VTRACE(("Activating appropriate texture state %d\n", Sampler));
457     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
458         ENTER_GL();
459         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
460         checkGLcall("glActiveTextureARB");
461         LEAVE_GL();
462         /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
463     } else if (Sampler > 0) {
464         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
465         return;
466     }
467
468     /* TODO: change this to a lookup table
469         LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
470         LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
471         etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
472         especially when there are a number of groups of states. */
473
474     TRACE("-----------------------> Updating the texture at Sampler %d to have new texture state information\n", Sampler);
475
476     /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list  */
477 #define APPLY_STATE(_state)     IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
478 /* these are the only two supported states that need to be applied */
479     APPLY_STATE(WINED3DTSS_TEXCOORDINDEX);
480     APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS);
481 #if 0 /* not supported at the moment */
482     APPLY_STATE(WINED3DTSS_BUMPENVMAT00);
483     APPLY_STATE(WINED3DTSS_BUMPENVMAT01);
484     APPLY_STATE(WINED3DTSS_BUMPENVMAT10);
485     APPLY_STATE(WINED3DTSS_BUMPENVMAT11);
486     APPLY_STATE(WINED3DTSS_BUMPENVLSCALE);
487     APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET);
488     APPLY_STATE(WINED3DTSS_RESULTARG);
489     APPLY_STATE(WINED3DTSS_CONSTANT);
490 #endif
491     /* a quick sanity check in case someone forgot to update this function */
492     if (WINED3D_HIGHEST_TEXTURE_STATE > WINED3DTSS_CONSTANT) {
493         FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This);
494     }
495 #undef APPLY_STATE
496
497     /* apply any sampler states that always need applying */
498     if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
499         tmpvalue.d = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPMAPLODBIAS];
500         glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
501                 GL_TEXTURE_LOD_BIAS_EXT,
502                 tmpvalue.f);
503         checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
504     }
505
506     D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
507     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
508     checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
509
510     /* TODO: NV_POINT_SPRITE */
511     if (GL_SUPPORT(ARB_POINT_SPRITE)) {
512         if (This->stateBlock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
513            /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
514            glDisable(GL_POINT_SMOOTH);
515
516            /* Centre the texture on the vertex */
517            VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
518            glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
519
520            VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
521            glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
522            checkGLcall("glTexEnvf(...)");
523            VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
524            glEnable( GL_POINT_SPRITE_ARB );
525            checkGLcall("glEnable(...)");
526         } else {
527            VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
528            glDisable( GL_POINT_SPRITE_ARB );
529            checkGLcall("glEnable(...)");
530         }
531     }
532
533     TRACE("-----------------------> Updated the texture at Sampler %d to have new texture state information\n", Sampler);
534 }
535
536 /**********************************************************
537  * IUnknown parts follows
538  **********************************************************/
539
540 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
541 {
542     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
543
544     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
545     if (IsEqualGUID(riid, &IID_IUnknown)
546         || IsEqualGUID(riid, &IID_IWineD3DBase)
547         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
548         IUnknown_AddRef(iface);
549         *ppobj = This;
550         return S_OK;
551     }
552     *ppobj = NULL;
553     return E_NOINTERFACE;
554 }
555
556 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
557     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
558     ULONG refCount = InterlockedIncrement(&This->ref);
559
560     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
561     return refCount;
562 }
563
564 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
565     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
566     ULONG refCount = InterlockedDecrement(&This->ref);
567
568     TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
569
570     if (!refCount) {
571         if (This->fbo) {
572             GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
573         }
574
575         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     /* Setup the implicit swapchain */
2083     TRACE("Creating implicit swapchain\n");
2084     if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
2085         WARN("Failed to create implicit swapchain\n");
2086         return WINED3DERR_INVALIDCALL;
2087     }
2088
2089     This->NumberOfSwapChains = 1;
2090     This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
2091     if(!This->swapchains) {
2092         ERR("Out of memory!\n");
2093         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
2094         return E_OUTOFMEMORY;
2095     }
2096     This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
2097
2098     if(swapchain->backBuffer && swapchain->backBuffer[0]) {
2099         TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
2100         This->render_targets[0] = swapchain->backBuffer[0];
2101     }
2102     else {
2103         TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
2104         This->render_targets[0] = swapchain->frontBuffer;
2105     }
2106     IWineD3DSurface_AddRef(This->render_targets[0]);
2107     /* Depth Stencil support */
2108     This->stencilBufferTarget = This->depthStencilBuffer;
2109     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
2110         set_depth_stencil_fbo(iface, This->depthStencilBuffer);
2111     }
2112     if (NULL != This->stencilBufferTarget) {
2113         IWineD3DSurface_AddRef(This->stencilBufferTarget);
2114     }
2115
2116     /* Set up some starting GL setup */
2117     ENTER_GL();
2118     /*
2119     * Initialize openGL extension related variables
2120     *  with Default values
2121     */
2122
2123     ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
2124     /* Setup all the devices defaults */
2125     IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
2126 #if 0
2127     IWineD3DImpl_CheckGraphicsMemory();
2128 #endif
2129     LEAVE_GL();
2130
2131     /* Initialize our list of GLSL programs */
2132     list_init(&This->glsl_shader_progs);
2133
2134     { /* Set a default viewport */
2135         WINED3DVIEWPORT vp;
2136         vp.X      = 0;
2137         vp.Y      = 0;
2138         vp.Width  = *(pPresentationParameters->BackBufferWidth);
2139         vp.Height = *(pPresentationParameters->BackBufferHeight);
2140         vp.MinZ   = 0.0f;
2141         vp.MaxZ   = 1.0f;
2142         IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
2143     }
2144
2145     /* Initialize the current view state */
2146     This->modelview_valid = 1;
2147     This->proj_valid = 0;
2148     This->view_ident = 1;
2149     This->last_was_rhw = 0;
2150     glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
2151     TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
2152
2153     /* Clear the screen */
2154     IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
2155
2156     /* Mark all states dirty. The Setters will not mark a state dirty when the new value is equal to the old value
2157      * This might create a problem in 2 situations:
2158      * ->The D3D default value is 0, but the opengl default value is something else
2159      * ->D3D7 unintialized D3D and reinitializes it. This way the context is destroyed, be the stateblock unchanged
2160      */
2161     for(state = 0; state <= STATE_HIGHEST; state++) {
2162         IWineD3DDeviceImpl_MarkStateDirty(This, state);
2163     }
2164
2165     This->d3d_initialized = TRUE;
2166     return WINED3D_OK;
2167 }
2168
2169 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
2170     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2171     int sampler;
2172     uint i;
2173     TRACE("(%p)\n", This);
2174
2175     if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
2176
2177     /* Delete the mouse cursor texture */
2178     if(This->cursorTexture) {
2179         ENTER_GL();
2180         glDeleteTextures(1, &This->cursorTexture);
2181         LEAVE_GL();
2182         This->cursorTexture = 0;
2183     }
2184
2185     for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
2186         IWineD3DDevice_SetTexture(iface, sampler, NULL);
2187     }
2188
2189     /* Release the buffers (with sanity checks)*/
2190     TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2191     if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2192         if(This->depthStencilBuffer != This->stencilBufferTarget)
2193             FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
2194     }
2195     This->stencilBufferTarget = NULL;
2196
2197     TRACE("Releasing the render target at %p\n", This->render_targets[0]);
2198     if(IWineD3DSurface_Release(This->render_targets[0]) >0){
2199           /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2200     }
2201     TRACE("Setting rendertarget to NULL\n");
2202     This->render_targets[0] = NULL;
2203
2204     if (This->depthStencilBuffer) {
2205         if(D3DCB_DestroyDepthStencilSurface(This->depthStencilBuffer) > 0) {
2206             FIXME("(%p) Something's still holding the depthStencilBuffer\n", This);
2207         }
2208         This->depthStencilBuffer = NULL;
2209     }
2210
2211     for(i=0; i < This->NumberOfSwapChains; i++) {
2212         TRACE("Releasing the implicit swapchain %d\n", i);
2213         if (D3DCB_DestroySwapChain(This->swapchains[i])  > 0) {
2214             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2215         }
2216     }
2217
2218     HeapFree(GetProcessHeap(), 0, This->swapchains);
2219     This->swapchains = NULL;
2220     This->NumberOfSwapChains = 0;
2221
2222     This->d3d_initialized = FALSE;
2223     return WINED3D_OK;
2224 }
2225
2226 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2227     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2228     TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2229
2230     /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2231      * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2232      * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
2233      * separately.
2234      */
2235     This->ddraw_fullscreen = fullscreen;
2236 }
2237
2238 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
2239     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2240
2241     DEVMODEW DevModeW;
2242     int i;
2243     const PixelFormatDesc *formatDesc  = getFormatDescEntry(pixelformat);
2244
2245     TRACE("(%p)->(%x,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
2246
2247     for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
2248         /* Ignore some modes if a description was passed */
2249         if ( (Width > 0)  && (Width != DevModeW.dmPelsWidth)) continue;
2250         if ( (Height > 0)  && (Height != DevModeW.dmPelsHeight)) continue;
2251         if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
2252
2253         TRACE("Enumerating %dx%d@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
2254
2255         if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
2256             return D3D_OK;
2257     }
2258
2259     return D3D_OK;
2260 }
2261
2262 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2263     DEVMODEW devmode;
2264     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2265     LONG ret;
2266     const PixelFormatDesc *formatDesc  = getFormatDescEntry(pMode->Format);
2267     RECT clip_rc;
2268
2269     TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2270
2271     /* Resize the screen even without a window:
2272      * The app could have unset it with SetCooperativeLevel, but not called
2273      * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2274      * but we don't have any hwnd
2275      */
2276
2277     devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2278     devmode.dmBitsPerPel = formatDesc->bpp * 8;
2279     if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2280     devmode.dmPelsWidth  = pMode->Width;
2281     devmode.dmPelsHeight = pMode->Height;
2282
2283     devmode.dmDisplayFrequency = pMode->RefreshRate;
2284     if (pMode->RefreshRate != 0)  {
2285         devmode.dmFields |= DM_DISPLAYFREQUENCY;
2286     }
2287
2288     /* Only change the mode if necessary */
2289     if( (This->ddraw_width == pMode->Width) &&
2290         (This->ddraw_height == pMode->Height) &&
2291         (This->ddraw_format == pMode->Format) &&
2292         (pMode->RefreshRate == 0) ) {
2293         return D3D_OK;
2294     }
2295
2296     ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2297     if (ret != DISP_CHANGE_SUCCESSFUL) {
2298         if(devmode.dmDisplayFrequency != 0) {
2299             WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2300             devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2301             devmode.dmDisplayFrequency = 0;
2302             ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2303         }
2304         if(ret != DISP_CHANGE_SUCCESSFUL) {
2305             return DDERR_INVALIDMODE;
2306         }
2307     }
2308
2309     /* Store the new values */
2310     This->ddraw_width = pMode->Width;
2311     This->ddraw_height = pMode->Height;
2312     This->ddraw_format = pMode->Format;
2313
2314     /* Only do this with a window of course */
2315     if(This->ddraw_window)
2316       MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2317
2318     /* And finally clip mouse to our screen */
2319     SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
2320     ClipCursor(&clip_rc);
2321
2322     return WINED3D_OK;
2323 }
2324
2325 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2326    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2327    *ppD3D= This->wineD3D;
2328    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
2329    IWineD3D_AddRef(*ppD3D);
2330    return WINED3D_OK;
2331 }
2332
2333 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2334     /** NOTE: There's a probably  a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
2335     * into the video ram as possible and seeing how many fit
2336     * you can also get the correct initial value from nvidia and ATI's driver via X
2337     * texture memory is video memory + AGP memory
2338     *******************/
2339     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2340     static BOOL showfixmes = TRUE;
2341     if (showfixmes) {
2342         FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2343          (wined3d_settings.emulated_textureram/(1024*1024)),
2344          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2345          showfixmes = FALSE;
2346     }
2347     TRACE("(%p) : simulating %dMB, returning %dMB left\n",  This,
2348          (wined3d_settings.emulated_textureram/(1024*1024)),
2349          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2350     /* return simulated texture memory left */
2351     return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2352 }
2353
2354
2355
2356 /*****
2357  * Get / Set FVF
2358  *****/
2359 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2360     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2361     HRESULT hr = WINED3D_OK;
2362
2363     /* Update the current state block */
2364     This->updateStateBlock->fvf              = fvf;
2365     This->updateStateBlock->changed.fvf      = TRUE;
2366     This->updateStateBlock->set.fvf          = TRUE;
2367
2368     TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2369     return hr;
2370 }
2371
2372
2373 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2374     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2375     TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2376     *pfvf = This->stateBlock->fvf;
2377     return WINED3D_OK;
2378 }
2379
2380 /*****
2381  * Get / Set Stream Source
2382  *****/
2383 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2384         IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
2385     IWineD3DVertexBuffer     *oldSrc;
2386
2387     /**TODO: instance and index data, see
2388     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2389     and
2390     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2391      **************/
2392
2393     /* D3d9 only, but shouldn't  hurt d3d8 */
2394     UINT streamFlags;
2395
2396     streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2397     if (streamFlags) {
2398         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2399            FIXME("stream index data not supported\n");
2400         }
2401         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2402            FIXME("stream instance data not supported\n");
2403         }
2404     }
2405
2406     StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2407
2408     if (StreamNumber >= MAX_STREAMS) {
2409         WARN("Stream out of range %d\n", StreamNumber);
2410         return WINED3DERR_INVALIDCALL;
2411     }
2412
2413     oldSrc = This->stateBlock->streamSource[StreamNumber];
2414     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2415
2416     This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2417     This->updateStateBlock->set.streamSource[StreamNumber]     = TRUE;
2418     This->updateStateBlock->streamStride[StreamNumber]         = Stride;
2419     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
2420     This->updateStateBlock->streamOffset[StreamNumber]         = OffsetInBytes;
2421     This->updateStateBlock->streamFlags[StreamNumber]          = streamFlags;
2422
2423     /* Handle recording of state blocks */
2424     if (This->isRecordingState) {
2425         TRACE("Recording... not performing anything\n");
2426         return WINED3D_OK;
2427     }
2428
2429     /* Same stream object: no action */
2430     if (oldSrc == pStreamData)
2431         return WINED3D_OK;
2432
2433     /* Need to do a getParent and pass the reffs up */
2434     /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2435     which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2436     so for now, just count internally   */
2437     if (pStreamData != NULL) {
2438         IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2439         if( (vbImpl->Flags & VBFLAG_STREAM) && vbImpl->stream != StreamNumber) {
2440             WARN("Assigning a Vertex Buffer to stream %d which is already assigned to stream %d\n", StreamNumber, vbImpl->stream);
2441         }
2442         vbImpl->stream = StreamNumber;
2443         vbImpl->Flags |= VBFLAG_STREAM;
2444         IWineD3DVertexBuffer_AddRef(pStreamData);
2445     }
2446     if (oldSrc != NULL) {
2447         ((IWineD3DVertexBufferImpl *) oldSrc)->Flags &= ~VBFLAG_STREAM;
2448         IWineD3DVertexBuffer_Release(oldSrc);
2449     }
2450
2451     return WINED3D_OK;
2452 }
2453
2454 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2455     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2456     UINT streamFlags;
2457
2458     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2459            This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2460
2461
2462     streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2463     if (streamFlags) {
2464         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2465            FIXME("stream index data not supported\n");
2466         }
2467         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2468             FIXME("stream instance data not supported\n");
2469         }
2470     }
2471
2472     StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2473
2474     if (StreamNumber >= MAX_STREAMS) {
2475         WARN("Stream out of range %d\n", StreamNumber);
2476         return WINED3DERR_INVALIDCALL;
2477     }
2478     *pStream = This->stateBlock->streamSource[StreamNumber];
2479     *pStride = This->stateBlock->streamStride[StreamNumber];
2480     if (pOffset) {
2481         *pOffset = This->stateBlock->streamOffset[StreamNumber];
2482     }
2483
2484      if (*pStream == NULL) {
2485         FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber);
2486         return  WINED3DERR_INVALIDCALL;
2487     }
2488
2489     IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2490     return WINED3D_OK;
2491 }
2492
2493 /*Should be quite easy, just an extension of vertexdata
2494 ref...
2495 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2496
2497 The divider is a bit odd though
2498
2499 VertexOffset = StartVertex / Divider * StreamStride +
2500                VertexIndex / Divider * StreamStride + StreamOffset
2501
2502 */
2503 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
2504     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2505
2506     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2507     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
2508
2509     This->updateStateBlock->changed.streamFreq[StreamNumber]  = TRUE;
2510     This->updateStateBlock->set.streamFreq[StreamNumber]      = TRUE;
2511     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
2512
2513     if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2514         FIXME("Stream indexing not fully supported\n");
2515     }
2516
2517     return WINED3D_OK;
2518 }
2519
2520 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
2521     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2522
2523     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2524     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2525
2526     TRACE("(%p) : returning %d\n", This, *Divider);
2527
2528     return WINED3D_OK;
2529 }
2530
2531 /*****
2532  * Get / Set & Multiply Transform
2533  *****/
2534 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2535     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2536
2537     /* Most of this routine, comments included copied from ddraw tree initially: */
2538     TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2539
2540     /* Handle recording of state blocks */
2541     if (This->isRecordingState) {
2542         TRACE("Recording... not performing anything\n");
2543         This->updateStateBlock->changed.transform[d3dts] = TRUE;
2544         This->updateStateBlock->set.transform[d3dts]     = TRUE;
2545         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2546         return WINED3D_OK;
2547     }
2548
2549     /*
2550      * If the new matrix is the same as the current one,
2551      * we cut off any further processing. this seems to be a reasonable
2552      * optimization because as was noticed, some apps (warcraft3 for example)
2553      * tend towards setting the same matrix repeatedly for some reason.
2554      *
2555      * From here on we assume that the new matrix is different, wherever it matters.
2556      */
2557     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2558         TRACE("The app is setting the same matrix over again\n");
2559         return WINED3D_OK;
2560     } else {
2561         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2562     }
2563
2564     /*
2565        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2566        where ViewMat = Camera space, WorldMat = world space.
2567
2568        In OpenGL, camera and world space is combined into GL_MODELVIEW
2569        matrix.  The Projection matrix stay projection matrix.
2570      */
2571
2572     /* Capture the times we can just ignore the change for now */
2573     if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
2574         This->modelview_valid = FALSE;
2575         return WINED3D_OK;
2576
2577     } else if (d3dts == WINED3DTS_PROJECTION) {
2578         This->proj_valid = FALSE;
2579         return WINED3D_OK;
2580
2581     } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
2582         /* Indexed Vertex Blending Matrices 256 -> 511  */
2583         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2584         FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
2585         return WINED3D_OK;
2586     }
2587
2588     /* Now we really are going to have to change a matrix */
2589     ENTER_GL();
2590
2591     if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
2592         /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2593     } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2594         unsigned int k;
2595
2596         /* If we are changing the View matrix, reset the light and clipping planes to the new view
2597          * NOTE: We have to reset the positions even if the light/plane is not currently
2598          *       enabled, since the call to enable it will not reset the position.
2599          * NOTE2: Apparently texture transforms do NOT need reapplying
2600          */
2601
2602         PLIGHTINFOEL *lightChain = NULL;
2603         This->modelview_valid = FALSE;
2604         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2605
2606         glMatrixMode(GL_MODELVIEW);
2607         checkGLcall("glMatrixMode(GL_MODELVIEW)");
2608         glPushMatrix();
2609         glLoadMatrixf((const float *)lpmatrix);
2610         checkGLcall("glLoadMatrixf(...)");
2611
2612         /* Reset lights */
2613         lightChain = This->stateBlock->lights;
2614         while (lightChain && lightChain->glIndex != -1) {
2615             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
2616             checkGLcall("glLightfv posn");
2617             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
2618             checkGLcall("glLightfv dirn");
2619             lightChain = lightChain->next;
2620         }
2621
2622         /* Reset Clipping Planes if clipping is enabled */
2623         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2624             glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
2625             checkGLcall("glClipPlane");
2626         }
2627         glPopMatrix();
2628
2629     } else { /* What was requested!?? */
2630         WARN("invalid matrix specified: %i\n", d3dts);
2631     }
2632
2633     /* Release lock, all done */
2634     LEAVE_GL();
2635     return WINED3D_OK;
2636
2637 }
2638 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2639     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2640     TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2641     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2642     return WINED3D_OK;
2643 }
2644
2645 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2646     WINED3DMATRIX *mat = NULL;
2647     WINED3DMATRIX temp;
2648
2649     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2650      * below means it will be recorded in a state block change, but it
2651      * works regardless where it is recorded.
2652      * If this is found to be wrong, change to StateBlock.
2653      */
2654     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2655     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2656
2657     if (State < HIGHEST_TRANSFORMSTATE)
2658     {
2659         mat = &This->updateStateBlock->transforms[State];
2660     } else {
2661         FIXME("Unhandled transform state!!\n");
2662     }
2663
2664     multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2665
2666     /* Apply change via set transform - will reapply to eg. lights this way */
2667     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2668 }
2669
2670 /*****
2671  * Get / Set Light
2672  *****/
2673 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2674    you can reference any indexes you want as long as that number max are enabled at any
2675    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2676    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2677    but when recording, just build a chain pretty much of commands to be replayed.                  */
2678
2679 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2680     float rho;
2681     PLIGHTINFOEL *object, *temp;
2682
2683     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2684     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2685
2686     /* If recording state block, just add to end of lights chain */
2687     if (This->isRecordingState) {
2688         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2689         if (NULL == object) {
2690             return WINED3DERR_OUTOFVIDEOMEMORY;
2691         }
2692         memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2693         object->OriginalIndex = Index;
2694         object->glIndex = -1;
2695         object->changed = TRUE;
2696
2697         /* Add to the END of the chain of lights changes to be replayed */
2698         if (This->updateStateBlock->lights == NULL) {
2699             This->updateStateBlock->lights = object;
2700         } else {
2701             temp = This->updateStateBlock->lights;
2702             while (temp->next != NULL) temp=temp->next;
2703             temp->next = object;
2704         }
2705         TRACE("Recording... not performing anything more\n");
2706         return WINED3D_OK;
2707     }
2708
2709     /* Ok, not recording any longer so do real work */
2710     object = This->stateBlock->lights;
2711     while (object != NULL && object->OriginalIndex != Index) object = object->next;
2712
2713     /* If we didn't find it in the list of lights, time to add it */
2714     if (object == NULL) {
2715         PLIGHTINFOEL *insertAt,*prevPos;
2716
2717         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2718         if (NULL == object) {
2719             return WINED3DERR_OUTOFVIDEOMEMORY;
2720         }
2721         object->OriginalIndex = Index;
2722         object->glIndex = -1;
2723
2724         /* Add it to the front of list with the idea that lights will be changed as needed
2725            BUT after any lights currently assigned GL indexes                             */
2726         insertAt = This->stateBlock->lights;
2727         prevPos  = NULL;
2728         while (insertAt != NULL && insertAt->glIndex != -1) {
2729             prevPos  = insertAt;
2730             insertAt = insertAt->next;
2731         }
2732
2733         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2734             This->stateBlock->lights = object;
2735         } else if (insertAt == NULL) { /* End of list */
2736             prevPos->next = object;
2737             object->prev = prevPos;
2738         } else { /* Middle of chain */
2739             if (prevPos == NULL) {
2740                 This->stateBlock->lights = object;
2741             } else {
2742                 prevPos->next = object;
2743             }
2744             object->prev = prevPos;
2745             object->next = insertAt;
2746             insertAt->prev = object;
2747         }
2748     }
2749
2750     /* Initialize the object */
2751     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,
2752           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2753           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2754           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2755     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2756           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2757     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2758
2759     /* Save away the information */
2760     memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2761
2762     switch (pLight->Type) {
2763     case WINED3DLIGHT_POINT:
2764         /* Position */
2765         object->lightPosn[0] = pLight->Position.x;
2766         object->lightPosn[1] = pLight->Position.y;
2767         object->lightPosn[2] = pLight->Position.z;
2768         object->lightPosn[3] = 1.0f;
2769         object->cutoff = 180.0f;
2770         /* FIXME: Range */
2771         break;
2772
2773     case WINED3DLIGHT_DIRECTIONAL:
2774         /* Direction */
2775         object->lightPosn[0] = -pLight->Direction.x;
2776         object->lightPosn[1] = -pLight->Direction.y;
2777         object->lightPosn[2] = -pLight->Direction.z;
2778         object->lightPosn[3] = 0.0;
2779         object->exponent     = 0.0f;
2780         object->cutoff       = 180.0f;
2781         break;
2782
2783     case WINED3DLIGHT_SPOT:
2784         /* Position */
2785         object->lightPosn[0] = pLight->Position.x;
2786         object->lightPosn[1] = pLight->Position.y;
2787         object->lightPosn[2] = pLight->Position.z;
2788         object->lightPosn[3] = 1.0;
2789
2790         /* Direction */
2791         object->lightDirn[0] = pLight->Direction.x;
2792         object->lightDirn[1] = pLight->Direction.y;
2793         object->lightDirn[2] = pLight->Direction.z;
2794         object->lightDirn[3] = 1.0;
2795
2796         /*
2797          * opengl-ish and d3d-ish spot lights use too different models for the
2798          * light "intensity" as a function of the angle towards the main light direction,
2799          * so we only can approximate very roughly.
2800          * however spot lights are rather rarely used in games (if ever used at all).
2801          * furthermore if still used, probably nobody pays attention to such details.
2802          */
2803         if (pLight->Falloff == 0) {
2804             rho = 6.28f;
2805         } else {
2806             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2807         }
2808         if (rho < 0.0001) rho = 0.0001f;
2809         object->exponent = -0.3/log(cos(rho/2));
2810         if (object->exponent > 128.0) {
2811                 object->exponent = 128.0;
2812         }
2813         object->cutoff = pLight->Phi*90/M_PI;
2814
2815         /* FIXME: Range */
2816         break;
2817
2818     default:
2819         FIXME("Unrecognized light type %d\n", pLight->Type);
2820     }
2821
2822     /* Update the live definitions if the light is currently assigned a glIndex */
2823     if (object->glIndex != -1) {
2824         setup_light(iface, object->glIndex, object);
2825     }
2826     return WINED3D_OK;
2827 }
2828
2829 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2830     PLIGHTINFOEL *lightInfo = NULL;
2831     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2832     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2833
2834     /* Locate the light in the live lights */
2835     lightInfo = This->stateBlock->lights;
2836     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2837
2838     if (lightInfo == NULL) {
2839         TRACE("Light information requested but light not defined\n");
2840         return WINED3DERR_INVALIDCALL;
2841     }
2842
2843     memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2844     return WINED3D_OK;
2845 }
2846
2847 /*****
2848  * Get / Set Light Enable
2849  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2850  *****/
2851 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2852     PLIGHTINFOEL *lightInfo = NULL;
2853     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2854     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2855
2856     /* Tests show true = 128...not clear why */
2857
2858     Enable = Enable? 128: 0;
2859
2860     /* If recording state block, just add to end of lights chain with changedEnable set to true */
2861     if (This->isRecordingState) {
2862         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2863         if (NULL == lightInfo) {
2864             return WINED3DERR_OUTOFVIDEOMEMORY;
2865         }
2866         lightInfo->OriginalIndex = Index;
2867         lightInfo->glIndex = -1;
2868         lightInfo->enabledChanged = TRUE;
2869         lightInfo->lightEnabled = Enable;
2870
2871         /* Add to the END of the chain of lights changes to be replayed */
2872         if (This->updateStateBlock->lights == NULL) {
2873             This->updateStateBlock->lights = lightInfo;
2874         } else {
2875             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2876             while (temp->next != NULL) temp=temp->next;
2877             temp->next = lightInfo;
2878         }
2879         TRACE("Recording... not performing anything more\n");
2880         return WINED3D_OK;
2881     }
2882
2883     /* Not recording... So, locate the light in the live lights */
2884     lightInfo = This->stateBlock->lights;
2885     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2886
2887     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2888     if (lightInfo == NULL) {
2889
2890         TRACE("Light enabled requested but light not defined, so defining one!\n");
2891         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2892
2893         /* Search for it again! Should be fairly quick as near head of list */
2894         lightInfo = This->stateBlock->lights;
2895         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2896         if (lightInfo == NULL) {
2897             FIXME("Adding default lights has failed dismally\n");
2898             return WINED3DERR_INVALIDCALL;
2899         }
2900     }
2901
2902     /* OK, we now have a light... */
2903     if (!Enable) {
2904
2905         /* If we are disabling it, check it was enabled, and
2906            still only do something if it has assigned a glIndex (which it should have!)   */
2907         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2908             TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2909             ENTER_GL();
2910             glDisable(GL_LIGHT0 + lightInfo->glIndex);
2911             checkGLcall("glDisable GL_LIGHT0+Index");
2912             LEAVE_GL();
2913         } else {
2914             TRACE("Nothing to do as light was not enabled\n");
2915         }
2916         lightInfo->lightEnabled = Enable;
2917     } else {
2918
2919         /* We are enabling it. If it is enabled, it's really simple */
2920         if (lightInfo->lightEnabled) {
2921             /* nop */
2922             TRACE("Nothing to do as light was enabled\n");
2923
2924         /* If it already has a glIndex, it's still simple */
2925         } else if (lightInfo->glIndex != -1) {
2926             TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2927             lightInfo->lightEnabled = Enable;
2928             ENTER_GL();
2929             glEnable(GL_LIGHT0 + lightInfo->glIndex);
2930             checkGLcall("glEnable GL_LIGHT0+Index already setup");
2931             LEAVE_GL();
2932
2933         /* Otherwise got to find space - lights are ordered gl indexes first */
2934         } else {
2935             PLIGHTINFOEL *bsf  = NULL;
2936             PLIGHTINFOEL *pos  = This->stateBlock->lights;
2937             PLIGHTINFOEL *prev = NULL;
2938             int           Index= 0;
2939             int           glIndex = -1;
2940
2941             /* Try to minimize changes as much as possible */
2942             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2943
2944                 /* Try to remember which index can be replaced if necessary */
2945                 if (bsf==NULL && !pos->lightEnabled) {
2946                     /* Found a light we can replace, save as best replacement */
2947                     bsf = pos;
2948                 }
2949
2950                 /* Step to next space */
2951                 prev = pos;
2952                 pos = pos->next;
2953                 Index ++;
2954             }
2955
2956             /* If we have too many active lights, fail the call */
2957             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2958                 FIXME("Program requests too many concurrent lights\n");
2959                 return WINED3DERR_INVALIDCALL;
2960
2961             /* If we have allocated all lights, but not all are enabled,
2962                reuse one which is not enabled                           */
2963             } else if (Index == This->maxConcurrentLights) {
2964                 /* use bsf - Simply swap the new light and the BSF one */
2965                 PLIGHTINFOEL *bsfNext = bsf->next;
2966                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2967
2968                 /* Sort out ends */
2969                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2970                 if (bsf->prev != NULL) {
2971                     bsf->prev->next = lightInfo;
2972                 } else {
2973                     This->stateBlock->lights = lightInfo;
2974                 }
2975
2976                 /* If not side by side, lots of chains to update */
2977                 if (bsf->next != lightInfo) {
2978                     lightInfo->prev->next = bsf;
2979                     bsf->next->prev = lightInfo;
2980                     bsf->next       = lightInfo->next;
2981                     bsf->prev       = lightInfo->prev;
2982                     lightInfo->next = bsfNext;
2983                     lightInfo->prev = bsfPrev;
2984
2985                 } else {
2986                     /* Simple swaps */
2987                     bsf->prev = lightInfo;
2988                     bsf->next = lightInfo->next;
2989                     lightInfo->next = bsf;
2990                     lightInfo->prev = bsfPrev;
2991                 }
2992
2993
2994                 /* Update states */
2995                 glIndex = bsf->glIndex;
2996                 bsf->glIndex = -1;
2997                 lightInfo->glIndex = glIndex;
2998                 lightInfo->lightEnabled = Enable;
2999
3000                 /* Finally set up the light in gl itself */
3001                 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
3002                 ENTER_GL();
3003                 setup_light(iface, glIndex, lightInfo);
3004                 glEnable(GL_LIGHT0 + glIndex);
3005                 checkGLcall("glEnable GL_LIGHT0 new setup");
3006                 LEAVE_GL();
3007
3008             /* If we reached the end of the allocated lights, with space in the
3009                gl lights, setup a new light                                     */
3010             } else if (pos->glIndex == -1) {
3011
3012                 /* We reached the end of the allocated gl lights, so already
3013                     know the index of the next one!                          */
3014                 glIndex = Index;
3015                 lightInfo->glIndex = glIndex;
3016                 lightInfo->lightEnabled = Enable;
3017
3018                 /* In an ideal world, it's already in the right place */
3019                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
3020                    /* No need to move it */
3021                 } else {
3022                     /* Remove this light from the list */
3023                     lightInfo->prev->next = lightInfo->next;
3024                     if (lightInfo->next != NULL) {
3025                         lightInfo->next->prev = lightInfo->prev;
3026                     }
3027
3028                     /* Add in at appropriate place (inbetween prev and pos) */
3029                     lightInfo->prev = prev;
3030                     lightInfo->next = pos;
3031                     if (prev == NULL) {
3032                         This->stateBlock->lights = lightInfo;
3033                     } else {
3034                         prev->next = lightInfo;
3035                     }
3036                     if (pos != NULL) {
3037                         pos->prev = lightInfo;
3038                     }
3039                 }
3040
3041                 /* Finally set up the light in gl itself */
3042                 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
3043                 ENTER_GL();
3044                 setup_light(iface, glIndex, lightInfo);
3045                 glEnable(GL_LIGHT0 + glIndex);
3046                 checkGLcall("glEnable GL_LIGHT0 new setup");
3047                 LEAVE_GL();
3048
3049             }
3050         }
3051     }
3052     return WINED3D_OK;
3053 }
3054
3055 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3056
3057     PLIGHTINFOEL *lightInfo = NULL;
3058     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3059     TRACE("(%p) : for idx(%d)\n", This, Index);
3060
3061     /* Locate the light in the live lights */
3062     lightInfo = This->stateBlock->lights;
3063     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3064
3065     if (lightInfo == NULL) {
3066         TRACE("Light enabled state requested but light not defined\n");
3067         return WINED3DERR_INVALIDCALL;
3068     }
3069     *pEnable = lightInfo->lightEnabled;
3070     return WINED3D_OK;
3071 }
3072
3073 /*****
3074  * Get / Set Clip Planes
3075  *****/
3076 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3077     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3078     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
3079
3080     /* Validate Index */
3081     if (Index >= GL_LIMITS(clipplanes)) {
3082         TRACE("Application has requested clipplane this device doesn't support\n");
3083         return WINED3DERR_INVALIDCALL;
3084     }
3085
3086     This->updateStateBlock->changed.clipplane[Index] = TRUE;
3087     This->updateStateBlock->set.clipplane[Index] = TRUE;
3088     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3089     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3090     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3091     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3092
3093     /* Handle recording of state blocks */
3094     if (This->isRecordingState) {
3095         TRACE("Recording... not performing anything\n");
3096         return WINED3D_OK;
3097     }
3098
3099     /* Apply it */
3100
3101     ENTER_GL();
3102
3103     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3104     glMatrixMode(GL_MODELVIEW);
3105     glPushMatrix();
3106     glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3107
3108     TRACE("Clipplane [%f,%f,%f,%f]\n",
3109           This->updateStateBlock->clipplane[Index][0],
3110           This->updateStateBlock->clipplane[Index][1],
3111           This->updateStateBlock->clipplane[Index][2],
3112           This->updateStateBlock->clipplane[Index][3]);
3113     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3114     checkGLcall("glClipPlane");
3115
3116     glPopMatrix();
3117     LEAVE_GL();
3118
3119     return WINED3D_OK;
3120 }
3121
3122 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3123     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3124     TRACE("(%p) : for idx %d\n", This, Index);
3125
3126     /* Validate Index */
3127     if (Index >= GL_LIMITS(clipplanes)) {
3128         TRACE("Application has requested clipplane this device doesn't support\n");
3129         return WINED3DERR_INVALIDCALL;
3130     }
3131
3132     pPlane[0] = This->stateBlock->clipplane[Index][0];
3133     pPlane[1] = This->stateBlock->clipplane[Index][1];
3134     pPlane[2] = This->stateBlock->clipplane[Index][2];
3135     pPlane[3] = This->stateBlock->clipplane[Index][3];
3136     return WINED3D_OK;
3137 }
3138
3139 /*****
3140  * Get / Set Clip Plane Status
3141  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3142  *****/
3143 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3144     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3145     FIXME("(%p) : stub\n", This);
3146     if (NULL == pClipStatus) {
3147       return WINED3DERR_INVALIDCALL;
3148     }
3149     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3150     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3151     return WINED3D_OK;
3152 }
3153
3154 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3155     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3156     FIXME("(%p) : stub\n", This);
3157     if (NULL == pClipStatus) {
3158       return WINED3DERR_INVALIDCALL;
3159     }
3160     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3161     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3162     return WINED3D_OK;
3163 }
3164
3165 /*****
3166  * Get / Set Material
3167  *****/
3168 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3169     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3170
3171     This->updateStateBlock->changed.material = TRUE;
3172     This->updateStateBlock->set.material = TRUE;
3173     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3174
3175     /* Handle recording of state blocks */
3176     if (This->isRecordingState) {
3177         TRACE("Recording... not performing anything\n");
3178         return WINED3D_OK;
3179     }
3180
3181     ENTER_GL();
3182     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3183         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3184     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3185         pMaterial->Ambient.b, pMaterial->Ambient.a);
3186     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3187         pMaterial->Specular.b, pMaterial->Specular.a);
3188     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3189         pMaterial->Emissive.b, pMaterial->Emissive.a);
3190     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3191
3192     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3193     checkGLcall("glMaterialfv(GL_AMBIENT)");
3194     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3195     checkGLcall("glMaterialfv(GL_DIFFUSE)");
3196
3197     /* Only change material color if specular is enabled, otherwise it is set to black */
3198     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3199        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3200        checkGLcall("glMaterialfv(GL_SPECULAR");
3201     } else {
3202        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3203        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3204        checkGLcall("glMaterialfv(GL_SPECULAR");
3205     }
3206     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3207     checkGLcall("glMaterialfv(GL_EMISSION)");
3208     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3209     checkGLcall("glMaterialf(GL_SHININESS");
3210
3211     LEAVE_GL();
3212     return WINED3D_OK;
3213 }
3214
3215 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3216     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3217     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3218     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3219         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3220     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3221         pMaterial->Ambient.b, pMaterial->Ambient.a);
3222     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3223         pMaterial->Specular.b, pMaterial->Specular.a);
3224     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3225         pMaterial->Emissive.b, pMaterial->Emissive.a);
3226     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3227
3228     return WINED3D_OK;
3229 }
3230
3231 /*****
3232  * Get / Set Indices
3233  *****/
3234 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3235                                              UINT BaseVertexIndex) {
3236     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
3237     IWineD3DIndexBuffer *oldIdxs;
3238
3239     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3240     oldIdxs = This->updateStateBlock->pIndexData;
3241
3242     This->updateStateBlock->changed.indices = TRUE;
3243     This->updateStateBlock->set.indices = TRUE;
3244     This->updateStateBlock->pIndexData = pIndexData;
3245     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3246
3247     /* Handle recording of state blocks */
3248     if (This->isRecordingState) {
3249         TRACE("Recording... not performing anything\n");
3250         return WINED3D_OK;
3251     }
3252
3253     if (NULL != pIndexData) {
3254         IWineD3DIndexBuffer_AddRef(pIndexData);
3255     }
3256     if (NULL != oldIdxs) {
3257         IWineD3DIndexBuffer_Release(oldIdxs);
3258     }
3259     return WINED3D_OK;
3260 }
3261
3262 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3263     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3264
3265     *ppIndexData = This->stateBlock->pIndexData;
3266
3267     /* up ref count on ppindexdata */
3268     if (*ppIndexData) {
3269         IWineD3DIndexBuffer_AddRef(*ppIndexData);
3270         *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3271         TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3272     }else{
3273         TRACE("(%p) No index data set\n", This);
3274     }
3275     TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3276
3277     return WINED3D_OK;
3278 }
3279
3280 /*****
3281  * Get / Set Viewports
3282  *****/
3283 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3284     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3285
3286     TRACE("(%p)\n", This);
3287     This->updateStateBlock->changed.viewport = TRUE;
3288     This->updateStateBlock->set.viewport = TRUE;
3289     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3290
3291     /* Handle recording of state blocks */
3292     if (This->isRecordingState) {
3293         TRACE("Recording... not performing anything\n");
3294         return WINED3D_OK;
3295     }
3296     This->viewport_changed = TRUE;
3297
3298     ENTER_GL();
3299
3300     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3301           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3302
3303     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3304     checkGLcall("glDepthRange");
3305     /* Note: GL requires lower left, DirectX supplies upper left */
3306     /* TODO: replace usage of renderTarget with context management */
3307     glViewport(pViewport->X,
3308                (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3309                pViewport->Width, pViewport->Height);
3310
3311     checkGLcall("glViewport");
3312
3313     LEAVE_GL();
3314
3315     return WINED3D_OK;
3316
3317 }
3318
3319 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3320     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3321     TRACE("(%p)\n", This);
3322     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3323     return WINED3D_OK;
3324 }
3325
3326 /*****
3327  * Get / Set Render States
3328  * TODO: Verify against dx9 definitions
3329  *****/
3330 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
3331
3332     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
3333     DWORD oldValue = This->stateBlock->renderState[State];
3334
3335     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3336
3337     This->updateStateBlock->changed.renderState[State] = TRUE;
3338     This->updateStateBlock->set.renderState[State] = TRUE;
3339     This->updateStateBlock->renderState[State] = Value;
3340
3341     /* Handle recording of state blocks */
3342     if (This->isRecordingState) {
3343         TRACE("Recording... not performing anything\n");
3344         return WINED3D_OK;
3345     }
3346
3347     /* Compared here and not before the assignment to allow proper stateblock recording */
3348     if(Value == oldValue) {
3349         TRACE("Application is setting the old value over, nothing to do\n");
3350     } else {
3351         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
3352     }
3353
3354     return WINED3D_OK;
3355 }
3356
3357 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
3358     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3359     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
3360     *pValue = This->stateBlock->renderState[State];
3361     return WINED3D_OK;
3362 }
3363
3364 /*****
3365  * Get / Set Sampler States
3366  * TODO: Verify against dx9 definitions
3367  *****/
3368
3369 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3370     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3371     /**
3372     * SetSampler is designed to allow for more than the standard up to 8 textures
3373     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
3374     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3375     *
3376     * http://developer.nvidia.com/object/General_FAQ.html#t6
3377     *
3378     * There are two new settings for GForce
3379     * the sampler one:
3380     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3381     * and the texture one:
3382     * GL_MAX_TEXTURE_COORDS_ARB.
3383     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3384      ******************/
3385     /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3386     if(Sampler >  GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3387          FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
3388             Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
3389         return WINED3DERR_INVALIDCALL;
3390     }
3391
3392     TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
3393         debug_d3dsamplerstate(Type), Type, Value);
3394     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
3395     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
3396     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3397
3398     /* Handle recording of state blocks */
3399     if (This->isRecordingState) {
3400         TRACE("Recording... not performing anything\n");
3401         return WINED3D_OK;
3402     }
3403
3404     return WINED3D_OK;
3405 }
3406
3407 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3408     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3409     /** TODO: check that sampler is in  range **/
3410     *Value = This->stateBlock->samplerState[Sampler][Type];
3411     TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
3412
3413     return WINED3D_OK;
3414 }
3415
3416 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3417     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3418     RECT windowRect;
3419     UINT winHeight;
3420
3421     GetClientRect(((IWineD3DSwapChainImpl *)This->swapchains[0])->win_handle, &windowRect);
3422     /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3423     * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3424     */
3425     winHeight = windowRect.bottom - windowRect.top;
3426     TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->bottom - winHeight,
3427           pRect->right - pRect->left, pRect->bottom - pRect->top);
3428     ENTER_GL();
3429     glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3430     checkGLcall("glScissor");
3431     LEAVE_GL();
3432
3433     return WINED3D_OK;
3434 }
3435
3436 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3437     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3438     GLint scissorBox[4];
3439
3440     ENTER_GL();
3441     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3442     glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3443     pRect->left = scissorBox[0];
3444     pRect->top = scissorBox[1];
3445     pRect->right = scissorBox[0] + scissorBox[2];
3446     pRect->bottom = scissorBox[1] + scissorBox[3];
3447     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3448     LEAVE_GL();
3449     return WINED3D_OK;
3450 }
3451
3452 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3453     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3454     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3455
3456     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3457
3458     This->updateStateBlock->vertexDecl = pDecl;
3459     This->updateStateBlock->changed.vertexDecl = TRUE;
3460     This->updateStateBlock->set.vertexDecl = TRUE;
3461
3462     if (This->isRecordingState) {
3463         TRACE("Recording... not performing anything\n");
3464     }
3465
3466     if (NULL != pDecl) {
3467         IWineD3DVertexDeclaration_AddRef(pDecl);
3468     }
3469     if (NULL != oldDecl) {
3470         IWineD3DVertexDeclaration_Release(oldDecl);
3471     }
3472     return WINED3D_OK;
3473 }
3474
3475 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3476     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3477
3478     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3479
3480     *ppDecl = This->stateBlock->vertexDecl;
3481     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3482     return WINED3D_OK;
3483 }
3484
3485 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3486     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3487     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3488
3489     This->updateStateBlock->vertexShader         = pShader;
3490     This->updateStateBlock->changed.vertexShader = TRUE;
3491     This->updateStateBlock->set.vertexShader     = TRUE;
3492
3493     if (This->isRecordingState) {
3494         TRACE("Recording... not performing anything\n");
3495     }
3496
3497     if (NULL != pShader) {
3498         IWineD3DVertexShader_AddRef(pShader);
3499     }
3500     if (NULL != oldShader) {
3501         IWineD3DVertexShader_Release(oldShader);
3502     }
3503
3504     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3505     /**
3506      * TODO: merge HAL shaders context switching from prototype
3507      */
3508     return WINED3D_OK;
3509 }
3510
3511 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3512     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3513
3514     if (NULL == ppShader) {
3515         return WINED3DERR_INVALIDCALL;
3516     }
3517     *ppShader = This->stateBlock->vertexShader;
3518     if( NULL != *ppShader)
3519         IWineD3DVertexShader_AddRef(*ppShader);
3520
3521     TRACE("(%p) : returning %p\n", This, *ppShader);
3522     return WINED3D_OK;
3523 }
3524
3525 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
3526     IWineD3DDevice *iface,
3527     UINT start,
3528     CONST BOOL *srcData,
3529     UINT count) {
3530
3531     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3532     int i, cnt = min(count, MAX_CONST_B - start);
3533
3534     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3535             iface, srcData, start, count);
3536
3537     if (srcData == NULL || cnt < 0)
3538         return WINED3DERR_INVALIDCALL;
3539
3540     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3541     for (i = 0; i < cnt; i++)
3542         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3543
3544     for (i = start; i < cnt + start; ++i) {
3545         This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
3546         This->updateStateBlock->set.vertexShaderConstantsB[i]     = TRUE;
3547     }
3548
3549     return WINED3D_OK;
3550 }
3551
3552 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
3553     IWineD3DDevice *iface,
3554     UINT start,
3555     BOOL *dstData,
3556     UINT count) {
3557
3558     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3559     int cnt = min(count, MAX_CONST_B - start);
3560
3561     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3562             iface, dstData, start, count);
3563
3564     if (dstData == NULL || cnt < 0)
3565         return WINED3DERR_INVALIDCALL;
3566
3567     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
3568     return WINED3D_OK;
3569 }
3570
3571 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
3572     IWineD3DDevice *iface,
3573     UINT start,
3574     CONST int *srcData,
3575     UINT count) {
3576
3577     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3578     int i, cnt = min(count, MAX_CONST_I - start);
3579
3580     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3581             iface, srcData, start, count);
3582
3583     if (srcData == NULL || cnt < 0)
3584         return WINED3DERR_INVALIDCALL;
3585
3586     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3587     for (i = 0; i < cnt; i++)
3588         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3589            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3590
3591     for (i = start; i < cnt + start; ++i) {
3592         This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
3593         This->updateStateBlock->set.vertexShaderConstantsI[i]     = TRUE;
3594     }
3595
3596     return WINED3D_OK;
3597 }
3598
3599 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
3600     IWineD3DDevice *iface,
3601     UINT start,
3602     int *dstData,
3603     UINT count) {
3604
3605     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3606     int cnt = min(count, MAX_CONST_I - start);
3607
3608     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3609             iface, dstData, start, count);
3610
3611     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
3612         return WINED3DERR_INVALIDCALL;
3613
3614     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3615     return WINED3D_OK;
3616 }
3617
3618 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3619     IWineD3DDevice *iface,
3620     UINT start,
3621     CONST float *srcData,
3622     UINT count) {
3623
3624     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3625     int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3626
3627     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3628             iface, srcData, start, count);
3629
3630     if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
3631         return WINED3DERR_INVALIDCALL;
3632
3633     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
3634     for (i = 0; i < cnt; i++)
3635         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3636            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3637
3638     for (i = start; i < cnt + start; ++i) {
3639         if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
3640             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3641             ptr->idx = i;
3642             list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
3643             This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
3644         }
3645         This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
3646     }
3647
3648     return WINED3D_OK;
3649 }
3650
3651 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3652     IWineD3DDevice *iface,
3653     UINT start,
3654     float *dstData,
3655     UINT count) {
3656
3657     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3658     int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3659
3660     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3661             iface, dstData, start, count);
3662
3663     if (dstData == NULL || cnt < 0)
3664         return WINED3DERR_INVALIDCALL;
3665
3666     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3667     return WINED3D_OK;
3668 }
3669
3670 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3671     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3672     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3673     This->updateStateBlock->pixelShader         = pShader;
3674     This->updateStateBlock->changed.pixelShader = TRUE;
3675     This->updateStateBlock->set.pixelShader     = TRUE;
3676
3677     /* Handle recording of state blocks */
3678     if (This->isRecordingState) {
3679         TRACE("Recording... not performing anything\n");
3680     }
3681
3682     if (NULL != pShader) {
3683         IWineD3DPixelShader_AddRef(pShader);
3684     }
3685     if (NULL != oldShader) {
3686         IWineD3DPixelShader_Release(oldShader);
3687         if(pShader == NULL) {
3688             /* Fixed function pipeline color args conflict with pixel shader setup, so we do not apply them when a pshader is
3689              * bound. Due to that we have to reapply all color ops when disabling pixel shaders.
3690              * When pixel shaders are handled by the state table too, the pshader function will take care for that, and this
3691              * will also handle draw -> SetPixelShader(NULL) -> SetPixelShader(!= NULL) -> draw cases better
3692              */
3693             int i;
3694             for(i = 0; i < MAX_TEXTURES; i++) {
3695                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3696             }
3697         }
3698     }
3699
3700     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3701     /**
3702      * TODO: merge HAL shaders context switching from prototype
3703      */
3704     return WINED3D_OK;
3705 }
3706
3707 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3708     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3709
3710     if (NULL == ppShader) {
3711         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3712         return WINED3DERR_INVALIDCALL;
3713     }
3714
3715     *ppShader =  This->stateBlock->pixelShader;
3716     if (NULL != *ppShader) {
3717         IWineD3DPixelShader_AddRef(*ppShader);
3718     }
3719     TRACE("(%p) : returning %p\n", This, *ppShader);
3720     return WINED3D_OK;
3721 }
3722
3723 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3724     IWineD3DDevice *iface,
3725     UINT start,
3726     CONST BOOL *srcData,
3727     UINT count) {
3728
3729     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3730     int i, cnt = min(count, MAX_CONST_B - start);
3731
3732     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3733             iface, srcData, start, count);
3734
3735     if (srcData == NULL || cnt < 0)
3736         return WINED3DERR_INVALIDCALL;
3737
3738     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3739     for (i = 0; i < cnt; i++)
3740         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3741
3742     for (i = start; i < cnt + start; ++i) {
3743         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3744         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
3745     }
3746
3747     return WINED3D_OK;
3748 }
3749
3750 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3751     IWineD3DDevice *iface,
3752     UINT start,
3753     BOOL *dstData,
3754     UINT count) {
3755
3756     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3757     int cnt = min(count, MAX_CONST_B - start);
3758
3759     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3760             iface, dstData, start, count);
3761
3762     if (dstData == NULL || cnt < 0)
3763         return WINED3DERR_INVALIDCALL;
3764
3765     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3766     return WINED3D_OK;
3767 }
3768
3769 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3770     IWineD3DDevice *iface,
3771     UINT start,
3772     CONST int *srcData,
3773     UINT count) {
3774
3775     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3776     int i, cnt = min(count, MAX_CONST_I - start);
3777
3778     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3779             iface, srcData, start, count);
3780
3781     if (srcData == NULL || cnt < 0)
3782         return WINED3DERR_INVALIDCALL;
3783
3784     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3785     for (i = 0; i < cnt; i++)
3786         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3787            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3788
3789     for (i = start; i < cnt + start; ++i) {
3790         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3791         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
3792     }
3793
3794     return WINED3D_OK;
3795 }
3796
3797 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3798     IWineD3DDevice *iface,
3799     UINT start,
3800     int *dstData,
3801     UINT count) {
3802
3803     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3804     int cnt = min(count, MAX_CONST_I - start);
3805
3806     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3807             iface, dstData, start, count);
3808
3809     if (dstData == NULL || cnt < 0)
3810         return WINED3DERR_INVALIDCALL;
3811
3812     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3813     return WINED3D_OK;
3814 }
3815
3816 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3817     IWineD3DDevice *iface,
3818     UINT start,
3819     CONST float *srcData,
3820     UINT count) {
3821
3822     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3823     int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3824
3825     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3826             iface, srcData, start, count);
3827
3828     if (srcData == NULL || cnt < 0)
3829         return WINED3DERR_INVALIDCALL;
3830
3831     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
3832     for (i = 0; i < cnt; i++)
3833         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3834            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3835
3836     for (i = start; i < cnt + start; ++i) {
3837         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3838             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3839             ptr->idx = i;
3840             list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3841             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3842         }
3843         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3844     }
3845
3846     return WINED3D_OK;
3847 }
3848
3849 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3850     IWineD3DDevice *iface,
3851     UINT start,
3852     float *dstData,
3853     UINT count) {
3854
3855     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3856     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3857
3858     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3859             iface, dstData, start, count);
3860
3861     if (dstData == NULL || cnt < 0)
3862         return WINED3DERR_INVALIDCALL;
3863
3864     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3865     return WINED3D_OK;
3866 }
3867
3868 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3869 static HRESULT
3870 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3871     char *dest_ptr, *dest_conv = NULL;
3872     unsigned int i;
3873     DWORD DestFVF = dest->fvf;
3874     WINED3DVIEWPORT vp;
3875     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3876     BOOL doClip;
3877     int numTextures;
3878
3879     if (SrcFVF & WINED3DFVF_NORMAL) {
3880         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3881     }
3882
3883     if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
3884         ERR("Source has no position mask\n");
3885         return WINED3DERR_INVALIDCALL;
3886     }
3887
3888     /* We might access VBOs from this code, so hold the lock */
3889     ENTER_GL();
3890
3891     if (dest->resource.allocatedMemory == NULL) {
3892         /* This may happen if we do direct locking into a vbo. Unlikely,
3893          * but theoretically possible(ddraw processvertices test)
3894          */
3895         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3896         if(!dest->resource.allocatedMemory) {
3897             LEAVE_GL();
3898             ERR("Out of memory\n");
3899             return E_OUTOFMEMORY;
3900         }
3901         if(dest->vbo) {
3902             void *src;
3903             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3904             checkGLcall("glBindBufferARB");
3905             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3906             if(src) {
3907                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3908             }
3909             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3910             checkGLcall("glUnmapBufferARB");
3911         }
3912     }
3913
3914     /* Get a pointer into the destination vbo(create one if none exists) and
3915      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3916      */
3917     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3918         CreateVBO(dest);
3919     }
3920
3921     if(dest->vbo) {
3922         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3923         dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
3924         if(!dest_conv) {
3925             ERR("glMapBuffer failed\n");
3926             /* Continue without storing converted vertices */
3927         }
3928     }
3929
3930     /* Should I clip?
3931      * a) WINED3DRS_CLIPPING is enabled
3932      * b) WINED3DVOP_CLIP is passed
3933      */
3934     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3935         static BOOL warned = FALSE;
3936         /*
3937          * The clipping code is not quite correct. Some things need
3938          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3939          * so disable clipping for now.
3940          * (The graphics in Half-Life are broken, and my processvertices
3941          *  test crashes with IDirect3DDevice3)
3942         doClip = TRUE;
3943          */
3944         doClip = FALSE;
3945         if(!warned) {
3946            warned = TRUE;
3947            FIXME("Clipping is broken and disabled for now\n");
3948         }
3949     } else doClip = FALSE;
3950     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3951     if(dest_conv) {
3952         dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3953     }
3954
3955     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3956                                  WINED3DTS_VIEW,
3957                                  &view_mat);
3958     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3959                                  WINED3DTS_PROJECTION,
3960                                  &proj_mat);
3961     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3962                                  WINED3DTS_WORLDMATRIX(0),
3963                                  &world_mat);
3964
3965     TRACE("View mat:\n");
3966     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); \
3967     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); \
3968     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); \
3969     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); \
3970
3971     TRACE("Proj mat:\n");
3972     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); \
3973     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); \
3974     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); \
3975     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); \
3976
3977     TRACE("World mat:\n");
3978     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); \
3979     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); \
3980     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); \
3981     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); \
3982
3983     /* Get the viewport */
3984     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3985     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3986           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3987
3988     multiply_matrix(&mat,&view_mat,&world_mat);
3989     multiply_matrix(&mat,&proj_mat,&mat);
3990
3991     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3992
3993     for (i = 0; i < dwCount; i+= 1) {
3994         unsigned int tex_index;
3995
3996         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3997              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3998             /* The position first */
3999             float *p =
4000               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
4001             float x, y, z, rhw;
4002             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4003
4004             /* Multiplication with world, view and projection matrix */
4005             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);
4006             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);
4007             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);
4008             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);
4009
4010             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4011
4012             /* WARNING: The following things are taken from d3d7 and were not yet checked
4013              * against d3d8 or d3d9!
4014              */
4015
4016             /* Clipping conditions: From
4017              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4018              *
4019              * A vertex is clipped if it does not match the following requirements
4020              * -rhw < x <= rhw
4021              * -rhw < y <= rhw
4022              *    0 < z <= rhw
4023              *    0 < rhw ( Not in d3d7, but tested in d3d7)
4024              *
4025              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4026              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4027              *
4028              */
4029
4030             if( !doClip ||
4031                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4032                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
4033                   ( rhw > eps ) ) ) {
4034
4035                 /* "Normal" viewport transformation (not clipped)
4036                  * 1) The values are divided by rhw
4037                  * 2) The y axis is negative, so multiply it with -1
4038                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4039                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4040                  * 4) Multiply x with Width/2 and add Width/2
4041                  * 5) The same for the height
4042                  * 6) Add the viewpoint X and Y to the 2D coordinates and
4043                  *    The minimum Z value to z
4044                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4045                  *
4046                  * Well, basically it's simply a linear transformation into viewport
4047                  * coordinates
4048                  */
4049
4050                 x /= rhw;
4051                 y /= rhw;
4052                 z /= rhw;
4053
4054                 y *= -1;
4055
4056                 x *= vp.Width / 2;
4057                 y *= vp.Height / 2;
4058                 z *= vp.MaxZ - vp.MinZ;
4059
4060                 x += vp.Width / 2 + vp.X;
4061                 y += vp.Height / 2 + vp.Y;
4062                 z += vp.MinZ;
4063
4064                 rhw = 1 / rhw;
4065             } else {
4066                 /* That vertex got clipped
4067                  * Contrary to OpenGL it is not dropped completely, it just
4068                  * undergoes a different calculation.
4069                  */
4070                 TRACE("Vertex got clipped\n");
4071                 x += rhw;
4072                 y += rhw;
4073
4074                 x  /= 2;
4075                 y  /= 2;
4076
4077                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
4078                  * outside of the main vertex buffer memory. That needs some more
4079                  * investigation...
4080                  */
4081             }
4082
4083             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
4084
4085
4086             ( (float *) dest_ptr)[0] = x;
4087             ( (float *) dest_ptr)[1] = y;
4088             ( (float *) dest_ptr)[2] = z;
4089             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
4090
4091             dest_ptr += 3 * sizeof(float);
4092
4093             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4094                 dest_ptr += sizeof(float);
4095             }
4096
4097             if(dest_conv) {
4098                 float w = 1 / rhw;
4099                 ( (float *) dest_conv)[0] = x * w;
4100                 ( (float *) dest_conv)[1] = y * w;
4101                 ( (float *) dest_conv)[2] = z * w;
4102                 ( (float *) dest_conv)[3] = w;
4103
4104                 dest_conv += 3 * sizeof(float);
4105
4106                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4107                     dest_conv += sizeof(float);
4108                 }
4109             }
4110         }
4111         if (DestFVF & WINED3DFVF_PSIZE) {
4112             dest_ptr += sizeof(DWORD);
4113             if(dest_conv) dest_conv += sizeof(DWORD);
4114         }
4115         if (DestFVF & WINED3DFVF_NORMAL) {
4116             float *normal =
4117               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
4118             /* AFAIK this should go into the lighting information */
4119             FIXME("Didn't expect the destination to have a normal\n");
4120             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4121             if(dest_conv) {
4122                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
4123             }
4124         }
4125
4126         if (DestFVF & WINED3DFVF_DIFFUSE) {
4127             DWORD *color_d = 
4128               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
4129             if(!color_d) {
4130                 static BOOL warned = FALSE;
4131
4132                 if(!warned) {
4133                     ERR("No diffuse color in source, but destination has one\n");
4134                     warned = TRUE;
4135                 }
4136
4137                 *( (DWORD *) dest_ptr) = 0xffffffff;
4138                 dest_ptr += sizeof(DWORD);
4139
4140                 if(dest_conv) {
4141                     *( (DWORD *) dest_conv) = 0xffffffff;
4142                     dest_conv += sizeof(DWORD);
4143                 }
4144             }
4145             else {
4146                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4147                 if(dest_conv) {
4148                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
4149                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
4150                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
4151                     dest_conv += sizeof(DWORD);
4152                 }
4153             }
4154         }
4155
4156         if (DestFVF & WINED3DFVF_SPECULAR) { 
4157             /* What's the color value in the feedback buffer? */
4158             DWORD *color_s = 
4159               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
4160             if(!color_s) {
4161                 static BOOL warned = FALSE;
4162
4163                 if(!warned) {
4164                     ERR("No specular color in source, but destination has one\n");
4165                     warned = TRUE;
4166                 }
4167
4168                 *( (DWORD *) dest_ptr) = 0xFF000000;
4169                 dest_ptr += sizeof(DWORD);
4170
4171                 if(dest_conv) {
4172                     *( (DWORD *) dest_conv) = 0xFF000000;
4173                     dest_conv += sizeof(DWORD);
4174                 }
4175             }
4176             else {
4177                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4178                 if(dest_conv) {
4179                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
4180                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
4181                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
4182                     dest_conv += sizeof(DWORD);
4183                 }
4184             }
4185         }
4186
4187         for (tex_index = 0; tex_index < numTextures; tex_index++) {
4188             float *tex_coord =
4189               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
4190                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
4191             if(!tex_coord) {
4192                 ERR("No source texture, but destination requests one\n");
4193                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4194                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4195             }
4196             else {
4197                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4198                 if(dest_conv) {
4199                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4200                 }
4201             }
4202         }
4203     }
4204
4205     if(dest_conv) {
4206         GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4207         checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
4208     }
4209
4210     LEAVE_GL();
4211
4212     return WINED3D_OK;
4213 }
4214 #undef copy_and_next
4215
4216 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4217     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4218     IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
4219     WineDirect3DVertexStridedData strided;
4220     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4221
4222     if (!SrcImpl) {
4223         WARN("NULL source vertex buffer\n");
4224         return WINED3DERR_INVALIDCALL;
4225     }
4226     /* We don't need the source vbo because this buffer is only used as
4227      * a source for ProcessVertices. Avoid wasting resources by converting the
4228      * buffer and loading the VBO
4229      */
4230     if(SrcImpl->vbo) {
4231         TRACE("Releasing the source vbo, it won't be needed\n");
4232
4233         if(!SrcImpl->resource.allocatedMemory) {
4234             /* Rescue the data from the buffer */
4235             void *src;
4236             SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
4237             if(!SrcImpl->resource.allocatedMemory) {
4238                 ERR("Out of memory\n");
4239                 return E_OUTOFMEMORY;
4240             }
4241
4242             ENTER_GL();
4243             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
4244             checkGLcall("glBindBufferARB");
4245
4246             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
4247             if(src) {
4248                 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
4249             }
4250
4251             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4252             checkGLcall("glUnmapBufferARB");
4253         } else {
4254             ENTER_GL();
4255         }
4256
4257         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
4258         checkGLcall("glBindBufferARB");
4259         GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
4260         checkGLcall("glDeleteBuffersARB");
4261         LEAVE_GL();
4262
4263         SrcImpl->vbo = 0;
4264     }
4265
4266     memset(&strided, 0, sizeof(strided));
4267     primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
4268
4269     return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4270 }
4271
4272 /*****
4273  * Apply / Get / Set Texture Stage States
4274  * TODO: Verify against dx9 definitions
4275  *****/
4276
4277 /* 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 */
4278 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4279     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4280     DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4281     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4282
4283     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4284
4285     /* Check that the stage is within limits  */
4286     if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
4287         TRACE("Attempt to access invalid texture rejected\n");
4288         return;
4289     }
4290
4291     ENTER_GL();
4292
4293     switch (Type) {
4294     case WINED3DTSS_ALPHAOP               :
4295     case WINED3DTSS_COLOROP               :
4296         /* nothing to do as moved to drawprim for now */
4297         break;
4298     case WINED3DTSS_ADDRESSW              :
4299 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4300             if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4301                 FIXME("Unrecognized or unsupported WINED3DTADDRESS_* value %d, state %d\n", Value, Type);
4302
4303             } else {
4304                 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4305                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4306                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4307                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4308             }
4309 #endif
4310     case WINED3DTSS_TEXCOORDINDEX         :
4311         {
4312             /* Handled from the state table */
4313         }
4314         break;
4315
4316         /* Unhandled */
4317     case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4318         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);
4319         break;
4320
4321     case WINED3DTSS_BUMPENVMAT00          :
4322     case WINED3DTSS_BUMPENVMAT01          :
4323         TRACE("BUMPENVMAT0%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4324         break;
4325     case WINED3DTSS_BUMPENVMAT10          :
4326     case WINED3DTSS_BUMPENVMAT11          :
4327         TRACE("BUMPENVMAT1%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4328         break;
4329
4330     case WINED3DTSS_BUMPENVLSCALE         :
4331       TRACE("BUMPENVLSCALE Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
4332       break;
4333
4334     case WINED3DTSS_BUMPENVLOFFSET        :
4335       TRACE("BUMPENVLOFFSET Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
4336       break;
4337
4338     case WINED3DTSS_RESULTARG             :
4339       TRACE("RESULTARG Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
4340       break;
4341
4342     default:
4343         /* Put back later: FIXME("(%p) : stub, Stage=%d, Type=%d, Value =%d\n", This, Stage, Type, Value); */
4344         TRACE("Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
4345     }
4346
4347     LEAVE_GL();
4348
4349     return;
4350 }
4351
4352 /*****
4353  * Get / Set Texture Stage States
4354  * TODO: Verify against dx9 definitions
4355  *****/
4356 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4357     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4358     DWORD oldColorOp = This->updateStateBlock->textureState[Stage][WINED3DTSS_COLOROP];
4359
4360     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4361
4362     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4363
4364     /* Reject invalid texture units */
4365     if (Stage >= GL_LIMITS(texture_stages)) {
4366         TRACE("Attempt to access invalid texture rejected\n");
4367         return WINED3DERR_INVALIDCALL;
4368     }
4369
4370     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4371     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
4372     This->updateStateBlock->textureState[Stage][Type]         = Value;
4373
4374     if (This->isRecordingState) {
4375         TRACE("Recording... not performing anything\n");
4376         return WINED3D_OK;
4377     }
4378
4379     if(Stage > This->stateBlock->lowest_disabled_stage &&
4380        StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
4381         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4382          * Changes in other states are important on disabled stages too
4383          */
4384         return WINED3D_OK;
4385     }
4386
4387     if(Type == WINED3DTSS_COLOROP) {
4388         int i;
4389
4390         if(Value == WINED3DTOP_DISABLE && oldColorOp != WINED3DTOP_DISABLE) {
4391             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4392              * they have to be disabled
4393              *
4394              * The current stage is dirtified below.
4395              */
4396             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
4397                 TRACE("Additionally dirtifying stage %d\n", i);
4398                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4399             }
4400             This->stateBlock->lowest_disabled_stage = Stage;
4401             TRACE("New lowest disabled: %d\n", Stage);
4402         } else if(Value != WINED3DTOP_DISABLE && oldColorOp == WINED3DTOP_DISABLE) {
4403             /* Previously disabled stage enabled. Stages above it may need enabling
4404              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4405              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4406              *
4407              * Again stage Stage doesn't need to be dirtified here, it is handled below.
4408              */
4409
4410             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
4411                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
4412                     break;
4413                 }
4414                 TRACE("Additionally dirtifying stage %d due to enable\n", i);
4415                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4416             }
4417             This->stateBlock->lowest_disabled_stage = i;
4418             TRACE("New lowest disabled: %d\n", i);
4419         }
4420         if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4421             /* TODO: Built a stage -> texture unit mapping for register combiners */
4422         }
4423     }
4424
4425     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
4426
4427     return WINED3D_OK;
4428 }
4429
4430 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4431     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4432     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4433     *pValue = This->updateStateBlock->textureState[Stage][Type];
4434     return WINED3D_OK;
4435 }
4436
4437 /*****
4438  * Get / Set Texture
4439  *****/
4440 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4441
4442     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4443     IWineD3DBaseTexture   *oldTexture;
4444
4445     oldTexture = This->updateStateBlock->textures[Stage];
4446     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
4447
4448 #if 0 /* TODO: check so vertex textures */
4449     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4450         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4451         return WINED3D_OK;
4452     }
4453 #endif
4454
4455     /* Reject invalid texture units */
4456     if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
4457         WARN("Attempt to access invalid texture rejected\n");
4458         return WINED3DERR_INVALIDCALL;
4459     }
4460
4461     if(pTexture != NULL) {
4462         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
4463          */
4464         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
4465             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4466             return WINED3DERR_INVALIDCALL;
4467         }
4468     }
4469
4470     oldTexture = This->updateStateBlock->textures[Stage];
4471     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
4472     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4473
4474     This->updateStateBlock->set.textures[Stage]     = TRUE;
4475     This->updateStateBlock->changed.textures[Stage] = TRUE;
4476     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4477     This->updateStateBlock->textures[Stage]         = pTexture;
4478
4479     /* Handle recording of state blocks */
4480     if (This->isRecordingState) {
4481         TRACE("Recording... not performing anything\n");
4482         return WINED3D_OK;
4483     }
4484
4485     /** NOTE: MSDN says that setTexture increases the reference count,
4486     * and the the application nust set the texture back to null (or have a leaky application),
4487     * This means we should pass the refcount up to the parent
4488      *******************************/
4489     if (NULL != This->updateStateBlock->textures[Stage]) {
4490         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4491         if(oldTexture == NULL) {
4492             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4493              * so the COLOROP and ALPHAOP have to be dirtified.
4494              */
4495             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4496             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4497         }
4498     }
4499
4500     if (NULL != oldTexture) {
4501         IWineD3DBaseTexture_Release(oldTexture);
4502         if(pTexture == NULL) {
4503             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4504             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4505         }
4506     }
4507
4508     /* Color keying is affected by the texture. Temporarily mark the color key state (=alpha test)
4509      * dirty until textures are integrated with the state management
4510      */
4511     if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
4512         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORKEYENABLE));
4513     }
4514
4515     return WINED3D_OK;
4516 }
4517
4518 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4519     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4520     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4521
4522     /* Reject invalid texture units */
4523     if (Stage >= GL_LIMITS(sampler_stages)) {
4524         TRACE("Attempt to access invalid texture rejected\n");
4525         return WINED3DERR_INVALIDCALL;
4526     }
4527     *ppTexture=This->stateBlock->textures[Stage];
4528     if (*ppTexture)
4529         IWineD3DBaseTexture_AddRef(*ppTexture);
4530
4531     return WINED3D_OK;
4532 }
4533
4534 /*****
4535  * Get Back Buffer
4536  *****/
4537 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4538                                                 IWineD3DSurface **ppBackBuffer) {
4539     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4540     IWineD3DSwapChain *swapChain;
4541     HRESULT hr;
4542
4543     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4544
4545     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4546     if (hr == WINED3D_OK) {
4547         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4548             IWineD3DSwapChain_Release(swapChain);
4549     } else {
4550         *ppBackBuffer = NULL;
4551     }
4552     return hr;
4553 }
4554
4555 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4556     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4557     WARN("(%p) : stub, calling idirect3d for now\n", This);
4558     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4559 }
4560
4561 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4562     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4563     IWineD3DSwapChain *swapChain;
4564     HRESULT hr;
4565
4566     if(iSwapChain > 0) {
4567         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4568         if (hr == WINED3D_OK) {
4569             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4570             IWineD3DSwapChain_Release(swapChain);
4571         } else {
4572             FIXME("(%p) Error getting display mode\n", This);
4573         }
4574     } else {
4575         /* Don't read the real display mode,
4576            but return the stored mode instead. X11 can't change the color
4577            depth, and some apps are pretty angry if they SetDisplayMode from
4578            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4579
4580            Also don't relay to the swapchain because with ddraw it's possible
4581            that there isn't a swapchain at all */
4582         pMode->Width = This->ddraw_width;
4583         pMode->Height = This->ddraw_height;
4584         pMode->Format = This->ddraw_format;
4585         pMode->RefreshRate = 0;
4586         hr = WINED3D_OK;
4587     }
4588
4589     return hr;
4590 }
4591
4592 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4593     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4594     TRACE("(%p)->(%p)\n", This, hWnd);
4595
4596     This->ddraw_window = hWnd;
4597     return WINED3D_OK;
4598 }
4599
4600 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4601     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4602     TRACE("(%p)->(%p)\n", This, hWnd);
4603
4604     *hWnd = This->ddraw_window;
4605     return WINED3D_OK;
4606 }
4607
4608 /*****
4609  * Stateblock related functions
4610  *****/
4611
4612 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4613     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4614     IWineD3DStateBlockImpl *object;
4615     HRESULT temp_result;
4616     
4617     TRACE("(%p)\n", This);
4618     
4619     if (This->isRecordingState) {
4620         return WINED3DERR_INVALIDCALL;
4621     }
4622     
4623     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4624     if (NULL == object ) {
4625         FIXME("(%p)Error allocating memory for stateblock\n", This);
4626         return E_OUTOFMEMORY;
4627     }
4628     TRACE("(%p) created object %p\n", This, object);
4629     object->wineD3DDevice= This;
4630     /** FIXME: object->parent       = parent; **/
4631     object->parent       = NULL;
4632     object->blockType    = WINED3DSBT_ALL;
4633     object->ref          = 1;
4634     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4635     
4636     temp_result = allocate_shader_constants(object);
4637     if (WINED3D_OK != temp_result)
4638         return temp_result;
4639
4640     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4641     This->updateStateBlock = object;
4642     This->isRecordingState = TRUE;
4643
4644     TRACE("(%p) recording stateblock %p\n",This , object);
4645     return WINED3D_OK;
4646 }
4647
4648 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4649     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4650
4651     if (!This->isRecordingState) {
4652         FIXME("(%p) not recording! returning error\n", This);
4653         *ppStateBlock = NULL;
4654         return WINED3DERR_INVALIDCALL;
4655     }
4656
4657     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4658     This->isRecordingState = FALSE;
4659     This->updateStateBlock = This->stateBlock;
4660     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4661     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4662     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4663     return WINED3D_OK;
4664 }
4665
4666 /*****
4667  * Scene related functions
4668  *****/
4669 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4670     /* At the moment we have no need for any functionality at the beginning
4671        of a scene                                                          */
4672     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4673     TRACE("(%p) : stub\n", This);
4674     return WINED3D_OK;
4675 }
4676
4677 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4678     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4679     TRACE("(%p)\n", This);
4680     ENTER_GL();
4681     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4682     glFlush();
4683     checkGLcall("glFlush");
4684
4685     TRACE("End Scene\n");
4686     /* If we're using FBOs this isn't needed */
4687     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_targets[0] != NULL) {
4688
4689         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4690         IUnknown *targetContainer = NULL;
4691         if (WINED3D_OK == IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4692             || WINED3D_OK == IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DDevice, (void **)&targetContainer)) {
4693             TRACE("(%p) : Texture rendertarget %p\n", This ,This->render_targets[0]);
4694             /** always dirtify for now. we must find a better way to see that surface have been modified
4695             (Modifications should will only occur via draw-primitive, but we do need better locking
4696             switching to render-to-texture should remove the overhead though.
4697             */
4698             IWineD3DSurface_SetPBufferState(This->render_targets[0], TRUE /* inPBuffer */, FALSE /* inTexture */);
4699             IWineD3DSurface_AddDirtyRect(This->render_targets[0], NULL);
4700             IWineD3DSurface_PreLoad(This->render_targets[0]);
4701             IWineD3DSurface_SetPBufferState(This->render_targets[0], FALSE /* inPBuffer */, FALSE /* inTexture */);
4702             IUnknown_Release(targetContainer);
4703         }
4704     }
4705     This->sceneEnded = TRUE;
4706     LEAVE_GL();
4707     return WINED3D_OK;
4708 }
4709
4710 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4711                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4712                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4713     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4714     IWineD3DSwapChain *swapChain = NULL;
4715     int i;
4716     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4717
4718     TRACE("(%p) Presenting the frame\n", This);
4719
4720     for(i = 0 ; i < swapchains ; i ++) {
4721
4722         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4723         TRACE("presentinng chain %d, %p\n", i, swapChain);
4724         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4725         IWineD3DSwapChain_Release(swapChain);
4726     }
4727
4728     return WINED3D_OK;
4729 }
4730
4731 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4732                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4733     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4734
4735     /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
4736       render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
4737       when the depth-buffer format does not contain stencil buffer information, this method fails. */
4738     GLbitfield     glMask = 0;
4739     GLboolean      old_ztest;
4740     GLfloat        old_z_clear_value;
4741     GLint          old_stencil_clear_value;
4742     GLfloat        old_color_clear_value[4];
4743     unsigned int   i;
4744     CONST WINED3DRECT* curRect;
4745
4746     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
4747           Count, pRects, Flags, Z, Stencil);
4748
4749     ENTER_GL();
4750
4751     glEnable(GL_SCISSOR_TEST);
4752     checkGLcall("glEnable GL_SCISSOR_TEST");
4753
4754     if (Count > 0 && pRects) {
4755         curRect = pRects;
4756     } else {
4757         curRect = NULL;
4758     }
4759
4760     /* Only set the values up once, as they are not changing */
4761     if (Flags & WINED3DCLEAR_STENCIL) {
4762         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4763         glClearStencil(Stencil);
4764         checkGLcall("glClearStencil");
4765         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4766         glStencilMask(0xFFFFFFFF);
4767     }
4768
4769     if (Flags & WINED3DCLEAR_ZBUFFER) {
4770         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4771         glDepthMask(GL_TRUE);
4772         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4773         glClearDepth(Z);
4774         checkGLcall("glClearDepth");
4775         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4776     }
4777
4778     if (Flags & WINED3DCLEAR_TARGET) {
4779         TRACE("Clearing screen with glClear to color %x\n", Color);
4780         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4781         glClearColor(D3DCOLOR_R(Color),
4782                      D3DCOLOR_G(Color),
4783                      D3DCOLOR_B(Color),
4784                      D3DCOLOR_A(Color));
4785         checkGLcall("glClearColor");
4786
4787         /* Clear ALL colors! */
4788         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4789         glMask = glMask | GL_COLOR_BUFFER_BIT;
4790     }
4791
4792     /* Now process each rect in turn */
4793     for (i = 0; i < Count || i == 0; i++) {
4794
4795         if (curRect) {
4796             /* Note gl uses lower left, width/height */
4797             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4798                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4799                   curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4800                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4801             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4802                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4803             checkGLcall("glScissor");
4804         } else {
4805             glScissor(This->stateBlock->viewport.X,
4806                       (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4807                       (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4808                       This->stateBlock->viewport.Width,
4809                       This->stateBlock->viewport.Height);
4810             checkGLcall("glScissor");
4811         }
4812
4813         /* Clear the selected rectangle (or full screen) */
4814         glClear(glMask);
4815         checkGLcall("glClear");
4816
4817         /* Step to the next rectangle */
4818         if (curRect) curRect = curRect + sizeof(WINED3DRECT);
4819     }
4820
4821     /* Restore the old values (why..?) */
4822     if (Flags & WINED3DCLEAR_STENCIL) {
4823         glClearStencil(old_stencil_clear_value);
4824         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4825     }
4826     if (Flags & WINED3DCLEAR_ZBUFFER) {
4827         glDepthMask(old_ztest);
4828         glClearDepth(old_z_clear_value);
4829     }
4830     if (Flags & WINED3DCLEAR_TARGET) {
4831         glClearColor(old_color_clear_value[0],
4832                      old_color_clear_value[1],
4833                      old_color_clear_value[2],
4834                      old_color_clear_value[3]);
4835         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4836                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4837                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4838                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4839     }
4840
4841     glDisable(GL_SCISSOR_TEST);
4842     checkGLcall("glDisable");
4843     LEAVE_GL();
4844
4845     return WINED3D_OK;
4846 }
4847
4848 /*****
4849  * Drawing functions
4850  *****/
4851 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4852                                                 UINT PrimitiveCount) {
4853
4854     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4855     This->stateBlock->streamIsUP = FALSE;
4856
4857     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4858                                debug_d3dprimitivetype(PrimitiveType),
4859                                StartVertex, PrimitiveCount);
4860     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4861                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
4862
4863
4864     return WINED3D_OK;
4865 }
4866
4867 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4868 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4869                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4870                                                            INT baseVIndex, UINT minIndex,
4871                                                            UINT NumVertices, UINT startIndex, UINT primCount) {
4872
4873     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4874     UINT                 idxStride = 2;
4875     IWineD3DIndexBuffer *pIB;
4876     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4877
4878     pIB = This->stateBlock->pIndexData;
4879     This->stateBlock->streamIsUP = FALSE;
4880
4881     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
4882           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4883           minIndex, NumVertices, startIndex, baseVIndex, primCount);
4884
4885     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4886     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4887         idxStride = 2;
4888     } else {
4889         idxStride = 4;
4890     }
4891
4892     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4893                    idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
4894
4895     return WINED3D_OK;
4896 }
4897
4898 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4899                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4900                                                     UINT VertexStreamZeroStride) {
4901     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4902
4903     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4904              debug_d3dprimitivetype(PrimitiveType),
4905              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4906
4907     /* release the stream source */
4908     if (This->stateBlock->streamSource[0] != NULL) {
4909         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4910     }
4911
4912     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4913     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4914     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4915     This->stateBlock->streamIsUP = TRUE;
4916
4917     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4918                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
4919
4920     /* MSDN specifies stream zero settings must be set to NULL */
4921     This->stateBlock->streamStride[0] = 0;
4922     This->stateBlock->streamSource[0] = NULL;
4923
4924     /*stream zero settings set to null at end, as per the msdn */
4925     return WINED3D_OK;
4926 }
4927
4928 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4929                                                              UINT MinVertexIndex, UINT NumVertices,
4930                                                              UINT PrimitiveCount, CONST void* pIndexData,
4931                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4932                                                              UINT VertexStreamZeroStride) {
4933     int                 idxStride;
4934     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4935
4936     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4937              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4938              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4939              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4940
4941     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4942         idxStride = 2;
4943     } else {
4944         idxStride = 4;
4945     }
4946
4947     /* release the stream and index data */
4948     if (This->stateBlock->streamSource[0] != NULL) {
4949         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4950     }
4951     if (This->stateBlock->pIndexData) {
4952         IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
4953     }
4954
4955     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4956     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4957     This->stateBlock->streamIsUP = TRUE;
4958     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4959
4960     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
4961
4962     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4963     This->stateBlock->streamSource[0] = NULL;
4964     This->stateBlock->streamStride[0] = 0;
4965     This->stateBlock->pIndexData = NULL;
4966
4967     return WINED3D_OK;
4968 }
4969
4970 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4971
4972     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
4973     return WINED3D_OK;
4974 }
4975  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4976 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4977     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4978     HRESULT hr = WINED3D_OK;
4979     WINED3DRESOURCETYPE sourceType;
4980     WINED3DRESOURCETYPE destinationType;
4981     int i ,levels;
4982
4983     /* TODO: think about moving the code into IWineD3DBaseTexture  */
4984
4985     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4986
4987     /* verify that the source and destination textures aren't NULL */
4988     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4989         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4990              This, pSourceTexture, pDestinationTexture);
4991         hr = WINED3DERR_INVALIDCALL;
4992     }
4993
4994     if (pSourceTexture == pDestinationTexture) {
4995         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4996              This, pSourceTexture, pDestinationTexture);
4997         hr = WINED3DERR_INVALIDCALL;
4998     }
4999     /* Verify that the source and destination textures are the same type */
5000     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5001     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5002
5003     if (sourceType != destinationType) {
5004         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5005              This);
5006         hr = WINED3DERR_INVALIDCALL;
5007     }
5008
5009     /* check that both textures have the identical numbers of levels  */
5010     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5011         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5012         hr = WINED3DERR_INVALIDCALL;
5013     }
5014
5015     if (WINED3D_OK == hr) {
5016
5017         /* Make sure that the destination texture is loaded */
5018         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5019
5020         /* Update every surface level of the texture */
5021         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5022
5023         switch (sourceType) {
5024         case WINED3DRTYPE_TEXTURE:
5025             {
5026                 IWineD3DSurface *srcSurface;
5027                 IWineD3DSurface *destSurface;
5028
5029                 for (i = 0 ; i < levels ; ++i) {
5030                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
5031                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5032                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5033                     IWineD3DSurface_Release(srcSurface);
5034                     IWineD3DSurface_Release(destSurface);
5035                     if (WINED3D_OK != hr) {
5036                         WARN("(%p) : Call to update surface failed\n", This);
5037                         return hr;
5038                     }
5039                 }
5040             }
5041             break;
5042         case WINED3DRTYPE_CUBETEXTURE:
5043             {
5044                 IWineD3DSurface *srcSurface;
5045                 IWineD3DSurface *destSurface;
5046                 WINED3DCUBEMAP_FACES faceType;
5047
5048                 for (i = 0 ; i < levels ; ++i) {
5049                     /* Update each cube face */
5050                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5051                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
5052                         if (WINED3D_OK != hr) {
5053                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5054                         } else {
5055                             TRACE("Got srcSurface %p\n", srcSurface);
5056                         }
5057                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5058                         if (WINED3D_OK != hr) {
5059                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5060                         } else {
5061                             TRACE("Got desrSurface %p\n", destSurface);
5062                         }
5063                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5064                         IWineD3DSurface_Release(srcSurface);
5065                         IWineD3DSurface_Release(destSurface);
5066                         if (WINED3D_OK != hr) {
5067                             WARN("(%p) : Call to update surface failed\n", This);
5068                             return hr;
5069                         }
5070                     }
5071                 }
5072             }
5073             break;
5074 #if 0 /* TODO: Add support for volume textures */
5075         case WINED3DRTYPE_VOLUMETEXTURE:
5076             {
5077                 IWineD3DVolume  srcVolume  = NULL;
5078                 IWineD3DSurface destVolume = NULL;
5079
5080                 for (i = 0 ; i < levels ; ++i) {
5081                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5082                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5083                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5084                     IWineD3DVolume_Release(srcSurface);
5085                     IWineD3DVolume_Release(destSurface);
5086                     if (WINED3D_OK != hr) {
5087                         WARN("(%p) : Call to update volume failed\n", This);
5088                         return hr;
5089                     }
5090                 }
5091             }
5092             break;
5093 #endif
5094         default:
5095             FIXME("(%p) : Unsupported source and destination type\n", This);
5096             hr = WINED3DERR_INVALIDCALL;
5097         }
5098     }
5099
5100     return hr;
5101 }
5102
5103 static HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5104                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5105                                                 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5106     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5107
5108     TRACE("(%p) : stub\n", This);
5109     return WINED3D_OK;
5110 }
5111 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5112     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5113     /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5114     *  NOTE It may be best to move the code into surface to occomplish this
5115     ****************************************/
5116
5117     WINED3DSURFACE_DESC surfaceDesc;
5118     unsigned int surfaceWidth, surfaceHeight;
5119     glDescriptor *targetGlDescription  = NULL;
5120     glDescriptor *surfaceGlDescription = NULL;
5121     IWineD3DSwapChainImpl *container = NULL;
5122     
5123     IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5124     IWineD3DSurface_GetGlDesc(pSurface,      &surfaceGlDescription);
5125     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5126
5127     surfaceDesc.Width  = &surfaceWidth;
5128     surfaceDesc.Height = &surfaceHeight;
5129     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5130    /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5131
5132     /* Ok, I may need to setup some kind of active swapchain reference on the device */
5133     IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5134     ENTER_GL();
5135     /* TODO: opengl Context switching for swapchains etc... */
5136     if (NULL != container  || pRenderTarget == This->render_targets[0] || pRenderTarget == This->depthStencilBuffer) {
5137         if (NULL != container  && (pRenderTarget == container->backBuffer[0])) {
5138             glReadBuffer(GL_BACK);
5139             vcheckGLcall("glReadBuffer(GL_BACK)");
5140         } else if ((NULL != container  && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->render_targets[0])) {
5141             glReadBuffer(GL_FRONT);
5142             vcheckGLcall("glReadBuffer(GL_FRONT)");
5143         } else if (pRenderTarget == This->depthStencilBuffer) {
5144             FIXME("Reading of depthstencil not yet supported\n");
5145         }
5146
5147         glReadPixels(0,
5148                     0,
5149                     surfaceWidth,
5150                     surfaceHeight,
5151                     surfaceGlDescription->glFormat,
5152                     surfaceGlDescription->glType,
5153                     (void *)IWineD3DSurface_GetData(pSurface));
5154         vcheckGLcall("glReadPixels(...)");
5155         if(NULL != container ){
5156             IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5157         }
5158     } else {
5159         IWineD3DBaseTexture *container;
5160         GLenum textureDimensions = GL_TEXTURE_2D;
5161
5162         if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5163             textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5164             IWineD3DBaseTexture_Release(container);
5165         }
5166         /* TODO: 2D -> Cube surface coppies etc.. */
5167         if (surfaceGlDescription->target != textureDimensions) {
5168             FIXME("(%p) : Texture dimension mismatch\n", This);
5169         }
5170         glEnable(textureDimensions);
5171         vcheckGLcall("glEnable(GL_TEXTURE_...)");
5172         /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5173         glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5174         vcheckGLcall("glBindTexture");
5175         glGetTexImage(surfaceGlDescription->target,
5176                         surfaceGlDescription->level,
5177                         surfaceGlDescription->glFormat,
5178                         surfaceGlDescription->glType,
5179                         (void *)IWineD3DSurface_GetData(pSurface));
5180         glDisable(textureDimensions);
5181         vcheckGLcall("glDisable(GL_TEXTURE_...)");
5182
5183     }
5184     LEAVE_GL();
5185     return WINED3D_OK;
5186 }
5187
5188 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5189     IWineD3DSwapChain *swapChain;
5190     HRESULT hr;
5191     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5192     if(hr == WINED3D_OK) {
5193         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5194                 IWineD3DSwapChain_Release(swapChain);
5195     }
5196     return hr;
5197 }
5198
5199 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5200     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5201     /* return a sensible default */
5202     *pNumPasses = 1;
5203     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5204     FIXME("(%p) : stub\n", This);
5205     return WINED3D_OK;
5206 }
5207
5208 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5209     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5210     int j;
5211     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5212     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5213         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5214         return WINED3DERR_INVALIDCALL;
5215     }
5216     for (j = 0; j < 256; ++j) {
5217         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5218         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5219         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5220         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5221     }
5222     TRACE("(%p) : returning\n", This);
5223     return WINED3D_OK;
5224 }
5225
5226 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5227     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5228     int j;
5229     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5230     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5231         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5232         return WINED3DERR_INVALIDCALL;
5233     }
5234     for (j = 0; j < 256; ++j) {
5235         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5236         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5237         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5238         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5239     }
5240     TRACE("(%p) : returning\n", This);
5241     return WINED3D_OK;
5242 }
5243
5244 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5245     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5246     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5247     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5248         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5249         return WINED3DERR_INVALIDCALL;
5250     }
5251     /*TODO: stateblocks */
5252     This->currentPalette = PaletteNumber;
5253     TRACE("(%p) : returning\n", This);
5254     return WINED3D_OK;
5255 }
5256
5257 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5258     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5259     if (PaletteNumber == NULL) {
5260         WARN("(%p) : returning Invalid Call\n", This);
5261         return WINED3DERR_INVALIDCALL;
5262     }
5263     /*TODO: stateblocks */
5264     *PaletteNumber = This->currentPalette;
5265     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5266     return WINED3D_OK;
5267 }
5268
5269 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5270     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5271     static BOOL showFixmes = TRUE;
5272     if (showFixmes) {
5273         FIXME("(%p) : stub\n", This);
5274         showFixmes = FALSE;
5275     }
5276
5277     This->softwareVertexProcessing = bSoftware;
5278     return WINED3D_OK;
5279 }
5280
5281
5282 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5283     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5284     static BOOL showFixmes = TRUE;
5285     if (showFixmes) {
5286         FIXME("(%p) : stub\n", This);
5287         showFixmes = FALSE;
5288     }
5289     return This->softwareVertexProcessing;
5290 }
5291
5292
5293 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5294     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5295     IWineD3DSwapChain *swapChain;
5296     HRESULT hr;
5297
5298     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5299
5300     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5301     if(hr == WINED3D_OK){
5302         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5303         IWineD3DSwapChain_Release(swapChain);
5304     }else{
5305         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5306     }
5307     return hr;
5308 }
5309
5310
5311 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5312     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5313     static BOOL showfixmes = TRUE;
5314     if(nSegments != 0.0f) {
5315         if( showfixmes) {
5316             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5317             showfixmes = FALSE;
5318         }
5319     }
5320     return WINED3D_OK;
5321 }
5322
5323 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5324     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5325     static BOOL showfixmes = TRUE;
5326     if( showfixmes) {
5327         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5328         showfixmes = FALSE;
5329     }
5330     return 0.0f;
5331 }
5332
5333 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5334     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5335     /** TODO: remove casts to IWineD3DSurfaceImpl
5336      *       NOTE: move code to surface to accomplish this
5337       ****************************************/
5338     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5339     int srcWidth, srcHeight;
5340     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5341     WINED3DFORMAT destFormat, srcFormat;
5342     UINT          destSize;
5343     int destLeft, destTop;
5344     WINED3DPOOL       srcPool, destPool;
5345     int offset    = 0;
5346     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5347     glDescriptor *glDescription = NULL;
5348     GLenum textureDimensions = GL_TEXTURE_2D;
5349     IWineD3DBaseTexture *baseTexture;
5350
5351     WINED3DSURFACE_DESC  winedesc;
5352
5353     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5354     memset(&winedesc, 0, sizeof(winedesc));
5355     winedesc.Width  = &srcSurfaceWidth;
5356     winedesc.Height = &srcSurfaceHeight;
5357     winedesc.Pool   = &srcPool;
5358     winedesc.Format = &srcFormat;
5359
5360     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5361
5362     winedesc.Width  = &destSurfaceWidth;
5363     winedesc.Height = &destSurfaceHeight;
5364     winedesc.Pool   = &destPool;
5365     winedesc.Format = &destFormat;
5366     winedesc.Size   = &destSize;
5367
5368     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5369
5370     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5371         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5372         return WINED3DERR_INVALIDCALL;
5373     }
5374
5375     if (destFormat == WINED3DFMT_UNKNOWN) {
5376         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5377         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5378
5379         /* Get the update surface description */
5380         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5381     }
5382
5383     /* Make sure the surface is loaded and up to date */
5384     IWineD3DSurface_PreLoad(pDestinationSurface);
5385
5386     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5387
5388     ENTER_GL();
5389
5390     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5391     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5392     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
5393     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5394     destTop    = pDestPoint  ? pDestPoint->y : 0;
5395
5396
5397     /* This function doesn't support compressed textures
5398     the pitch is just bytesPerPixel * width */
5399     if(srcWidth != srcSurfaceWidth  || (pSourceRect != NULL && pSourceRect->left != 0) ){
5400         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5401         offset   += pSourceRect->left * pSrcSurface->bytesPerPixel;
5402         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5403     }
5404     /* TODO DXT formats */
5405
5406     if(pSourceRect != NULL && pSourceRect->top != 0){
5407        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5408     }
5409     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5410     ,This
5411     ,glDescription->level
5412     ,destLeft
5413     ,destTop
5414     ,srcWidth
5415     ,srcHeight
5416     ,glDescription->glFormat
5417     ,glDescription->glType
5418     ,IWineD3DSurface_GetData(pSourceSurface)
5419     );
5420
5421     /* Sanity check */
5422     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5423
5424         /* need to lock the surface to get the data */
5425         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5426     }
5427
5428     /* TODO: Cube and volume support */
5429     if(rowoffset != 0){
5430         /* not a whole row so we have to do it a line at a time */
5431         int j;
5432
5433         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5434         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5435
5436         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5437
5438                 glTexSubImage2D(glDescription->target
5439                     ,glDescription->level
5440                     ,destLeft
5441                     ,j
5442                     ,srcWidth
5443                     ,1
5444                     ,glDescription->glFormat
5445                     ,glDescription->glType
5446                     ,data /* could be quicker using */
5447                 );
5448             data += rowoffset;
5449         }
5450
5451     } else { /* Full width, so just write out the whole texture */
5452
5453         if (WINED3DFMT_DXT1 == destFormat ||
5454             WINED3DFMT_DXT2 == destFormat ||
5455             WINED3DFMT_DXT3 == destFormat ||
5456             WINED3DFMT_DXT4 == destFormat ||
5457             WINED3DFMT_DXT5 == destFormat) {
5458             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5459                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5460                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5461                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5462                 } if (destFormat != srcFormat) {
5463                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5464                 } else {
5465                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5466                                                         glDescription->level,
5467                                                         glDescription->glFormatInternal,
5468                                                         srcWidth,
5469                                                         srcHeight,
5470                                                         0,
5471                                                         destSize,
5472                                                         IWineD3DSurface_GetData(pSourceSurface));
5473                 }
5474             } else {
5475                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5476             }
5477
5478
5479         } else {
5480             if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5481
5482                 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5483                 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5484                 data returned by GetData non-power2 width/height with hardware non-power2
5485                 pow2Width/height are set to surface width height, repacking isn't needed so it
5486                 doesn't matter which function gets called. */
5487                 glTexSubImage2D(glDescription->target
5488                         ,glDescription->level
5489                         ,destLeft
5490                         ,destTop
5491                         ,srcWidth
5492                         ,srcHeight
5493                         ,glDescription->glFormat
5494                         ,glDescription->glType
5495                         ,IWineD3DSurface_GetData(pSourceSurface)
5496                     );
5497             } else {
5498
5499                 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5500                 glTexSubImage2D(glDescription->target
5501                     ,glDescription->level
5502                     ,destLeft
5503                     ,destTop
5504                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5505                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5506                     ,glDescription->glFormat
5507                     ,glDescription->glType
5508                     ,IWineD3DSurface_GetData(pSourceSurface)
5509                 );
5510             }
5511
5512         }
5513      }
5514     checkGLcall("glTexSubImage2D");
5515     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
5516
5517     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5518      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5519      * surface bigger than it needs to be hmm.. */
5520     if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5521         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5522         IWineD3DBaseTexture_Release(baseTexture);
5523     }
5524
5525     glDisable(textureDimensions); /* This needs to be managed better.... */
5526     LEAVE_GL();
5527
5528     return WINED3D_OK;
5529 }
5530
5531 /* Implementation details at http://developer.nvidia.com/attach/6494
5532 and
5533 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5534 hmm.. no longer supported use
5535 OpenGL evaluators or  tessellate surfaces within your application.
5536 */
5537
5538 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5539 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5540     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5541     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5542     FIXME("(%p) : Stub\n", This);
5543     return WINED3D_OK;
5544
5545 }
5546
5547 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5548 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5549     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5550     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5551     FIXME("(%p) : Stub\n", This);
5552     return WINED3D_OK;
5553 }
5554
5555 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5556     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5557     TRACE("(%p) Handle(%d)\n", This, Handle);
5558     FIXME("(%p) : Stub\n", This);
5559     return WINED3D_OK;
5560 }
5561
5562 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
5563     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5564     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
5565     DDBLTFX BltFx;
5566     TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
5567
5568     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
5569         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5570         return WINED3DERR_INVALIDCALL;
5571     }
5572
5573     /* Just forward this to the DirectDraw blitting engine */
5574     memset(&BltFx, 0, sizeof(BltFx));
5575     BltFx.dwSize = sizeof(BltFx);
5576     BltFx.u5.dwFillColor = color;
5577     return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
5578 }
5579
5580 /* rendertarget and deptth stencil functions */
5581 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5582     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5583
5584     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5585         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5586         return WINED3DERR_INVALIDCALL;
5587     }
5588
5589     *ppRenderTarget = This->render_targets[RenderTargetIndex];
5590     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5591     /* Note inc ref on returned surface */
5592     if(*ppRenderTarget != NULL)
5593         IWineD3DSurface_AddRef(*ppRenderTarget);
5594     return WINED3D_OK;
5595 }
5596
5597 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
5598     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5599     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
5600     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
5601     IWineD3DSwapChainImpl *Swapchain;
5602     HRESULT hr;
5603
5604     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
5605
5606     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
5607     if(hr != WINED3D_OK) {
5608         ERR("Can't get the swapchain\n");
5609         return hr;
5610     }
5611
5612     /* Make sure to release the swapchain */
5613     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
5614
5615     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
5616         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5617         return WINED3DERR_INVALIDCALL;
5618     }
5619     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
5620         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5621         return WINED3DERR_INVALIDCALL;
5622     }
5623
5624     if(Swapchain->frontBuffer != Front) {
5625         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
5626
5627         if(Swapchain->frontBuffer)
5628             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
5629         Swapchain->frontBuffer = Front;
5630
5631         if(Swapchain->frontBuffer) {
5632             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
5633         }
5634     }
5635
5636     if(Back && !Swapchain->backBuffer) {
5637         /* We need memory for the back buffer array - only one back buffer this way */
5638         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
5639         if(!Swapchain->backBuffer) {
5640             ERR("Out of memory\n");
5641             return E_OUTOFMEMORY;
5642         }
5643     }
5644
5645     if(Swapchain->backBuffer[0] != Back) {
5646         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
5647         ENTER_GL();
5648         if(!Swapchain->backBuffer[0]) {
5649             /* GL was told to draw to the front buffer at creation,
5650              * undo that
5651              */
5652             glDrawBuffer(GL_BACK);
5653             checkGLcall("glDrawBuffer(GL_BACK)");
5654             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
5655             Swapchain->presentParms.BackBufferCount = 1;
5656         } else if (!Back) {
5657             /* That makes problems - disable for now */
5658             /* glDrawBuffer(GL_FRONT); */
5659             checkGLcall("glDrawBuffer(GL_FRONT)");
5660             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
5661             Swapchain->presentParms.BackBufferCount = 0;
5662         }
5663         LEAVE_GL();
5664
5665         if(Swapchain->backBuffer[0])
5666             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
5667         Swapchain->backBuffer[0] = Back;
5668
5669         if(Swapchain->backBuffer[0]) {
5670             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5671         } else {
5672             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5673         }
5674
5675     }
5676
5677     return WINED3D_OK;
5678 }
5679
5680 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5681     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5682     *ppZStencilSurface = This->depthStencilBuffer;
5683     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5684
5685     if(*ppZStencilSurface != NULL) {
5686         /* Note inc ref on returned surface */
5687         IWineD3DSurface_AddRef(*ppZStencilSurface);
5688     }
5689     return WINED3D_OK;
5690 }
5691
5692 static void bind_fbo(IWineD3DDevice *iface) {
5693     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5694
5695     if (!This->fbo) {
5696         GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
5697         checkGLcall("glGenFramebuffersEXT()");
5698     }
5699     GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
5700     checkGLcall("glBindFramebuffer()");
5701 }
5702
5703 /* TODO: Handle stencil attachments */
5704 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5705     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5706     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5707
5708     This->depth_copy_state = WINED3D_DCS_NO_COPY;
5709
5710     bind_fbo(iface);
5711
5712     if (depth_stencil_impl) {
5713         GLenum texttarget, target;
5714
5715         IWineD3DSurface_PreLoad(depth_stencil);
5716         texttarget = depth_stencil_impl->glDescription.target;
5717         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5718
5719         glBindTexture(target, depth_stencil_impl->glDescription.textureName);
5720         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5721         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5722         glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5723         glBindTexture(target, 0);
5724
5725         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5726         checkGLcall("glFramebufferTexture2DEXT()");
5727     } else {
5728         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5729         checkGLcall("glFramebufferTexture2DEXT()");
5730     }
5731
5732     if (!This->render_offscreen) {
5733         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5734         checkGLcall("glBindFramebuffer()");
5735     }
5736 }
5737
5738 static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5739     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5740     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5741
5742     if (idx >= GL_LIMITS(buffers)) {
5743         ERR("%p : Trying to set render target %d, but only %d supported\n", This, idx, GL_LIMITS(buffers));
5744     }
5745
5746     bind_fbo(iface);
5747
5748     if (rtimpl) {
5749         GLenum texttarget, target;
5750
5751         IWineD3DSurface_PreLoad(render_target);
5752         texttarget = rtimpl->glDescription.target;
5753         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5754
5755         glBindTexture(target, rtimpl->glDescription.textureName);
5756         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5757         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5758         glBindTexture(target, 0);
5759
5760         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, rtimpl->glDescription.textureName, 0));
5761         checkGLcall("glFramebufferTexture2DEXT()");
5762
5763         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5764     } else {
5765         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5766         checkGLcall("glFramebufferTexture2DEXT()");
5767
5768         This->draw_buffers[idx] = GL_NONE;
5769     }
5770
5771     if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5772         GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5773         checkGLcall("glDrawBuffers()");
5774     }
5775
5776     if (!This->render_offscreen) {
5777         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5778         checkGLcall("glBindFramebuffer()");
5779     }
5780 }
5781
5782 /* internal static helper functions */
5783 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5784                                                 IWineD3DSurface *RenderSurface);
5785
5786 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5787     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5788     HRESULT  hr = WINED3D_OK;
5789     WINED3DVIEWPORT viewport;
5790
5791     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5792
5793     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5794         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5795         return WINED3DERR_INVALIDCALL;
5796     }
5797
5798     /* MSDN says that null disables the render target
5799     but a device must always be associated with a render target
5800     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5801
5802     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5803     for more details
5804     */
5805     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5806         FIXME("Trying to set render target 0 to NULL\n");
5807         return WINED3DERR_INVALIDCALL;
5808     }
5809     /* TODO: replace Impl* usage with interface usage */
5810     if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5811         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);
5812         return WINED3DERR_INVALIDCALL;
5813     }
5814     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5815      *        builds, but I think wine counts as a 'debug' build for now.
5816       ******************************/
5817     /* If we are trying to set what we already have, don't bother */
5818     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5819         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5820     } else {
5821         /* Otherwise, set the render target up */
5822
5823         if (!This->sceneEnded) {
5824             IWineD3DDevice_EndScene(iface);
5825         }
5826         TRACE("clearing renderer\n");
5827         /* IWineD3DDeviceImpl_CleanRender(iface); */
5828         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5829         depending on the renter target implementation being used.
5830         A shared context implementation will share all buffers between all rendertargets (including swapchains),
5831         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5832         stencil buffer and incure an extra memory overhead */
5833         if (RenderTargetIndex == 0) {
5834             hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5835         } else {
5836             hr = WINED3D_OK;
5837         }
5838
5839         /* Replace the render target */
5840         if (This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5841         This->render_targets[RenderTargetIndex] = pRenderTarget;
5842         if (pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5843
5844         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5845             set_render_target_fbo(iface, RenderTargetIndex, pRenderTarget);
5846         }
5847     }
5848
5849     if (SUCCEEDED(hr)) {
5850         /* Finally, reset the viewport as the MSDN states. */
5851         /* TODO: Replace impl usage */
5852         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5853         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5854         viewport.X      = 0;
5855         viewport.Y      = 0;
5856         viewport.MaxZ   = 1.0f;
5857         viewport.MinZ   = 0.0f;
5858         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5859     } else {
5860         FIXME("Unknown error setting the render target\n");
5861     }
5862     This->sceneEnded = FALSE;
5863     return hr;
5864 }
5865
5866 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5867     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5868     HRESULT  hr = WINED3D_OK;
5869     IWineD3DSurface *tmp;
5870
5871     TRACE("(%p) Swapping z-buffer\n",This);
5872
5873     if (pNewZStencil == This->stencilBufferTarget) {
5874         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5875     } else {
5876         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5877         * depending on the renter target implementation being used.
5878         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5879         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5880         * stencil buffer and incure an extra memory overhead
5881          ******************************************************/
5882
5883
5884         tmp = This->stencilBufferTarget;
5885         This->stencilBufferTarget = pNewZStencil;
5886         /* should we be calling the parent or the wined3d surface? */
5887         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5888         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5889         hr = WINED3D_OK;
5890         /** TODO: glEnable/glDisable on depth/stencil    depending on
5891          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
5892           **********************************************************/
5893         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5894             set_depth_stencil_fbo(iface, pNewZStencil);
5895         }
5896     }
5897
5898     return hr;
5899 }
5900
5901
5902 #ifdef GL_VERSION_1_3
5903 /* Internal functions not in DirectX */
5904  /** TODO: move this off to the opengl context manager
5905  *(the swapchain doesn't need to know anything about offscreen rendering!)
5906   ****************************************************/
5907
5908 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5909 {
5910     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5911
5912     TRACE("(%p), %p\n", This, swapchain);
5913
5914     if (swapchain->win != swapchain->drawable) {
5915         /* Set everything back the way it ws */
5916         swapchain->render_ctx = swapchain->glCtx;
5917         swapchain->drawable   = swapchain->win;
5918     }
5919     return WINED3D_OK;
5920 }
5921
5922 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5923 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5924     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5925     int i;
5926     unsigned int width;
5927     unsigned int height;
5928     WINED3DFORMAT format;
5929     WINED3DSURFACE_DESC surfaceDesc;
5930     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5931     surfaceDesc.Width  = &width;
5932     surfaceDesc.Height = &height;
5933     surfaceDesc.Format = &format;
5934     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5935     *context = NULL;
5936     /* I need a get width/height function (and should do something with the format) */
5937     for (i = 0; i < CONTEXT_CACHE; ++i) {
5938         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5939         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5940         the pSurface can be set to 0 allowing it to be reused from cache **/
5941         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5942           && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5943             *context = &This->contextCache[i];
5944             break;
5945         }
5946         if (This->contextCache[i].Width == 0) {
5947             This->contextCache[i].pSurface = pSurface;
5948             This->contextCache[i].Width    = width;
5949             This->contextCache[i].Height   = height;
5950             *context = &This->contextCache[i];
5951             break;
5952         }
5953     }
5954     if (i == CONTEXT_CACHE) {
5955         int minUsage = 0x7FFFFFFF; /* MAX_INT */
5956         glContext *dropContext = 0;
5957         for (i = 0; i < CONTEXT_CACHE; i++) {
5958             if (This->contextCache[i].usedcount < minUsage) {
5959                 dropContext = &This->contextCache[i];
5960                 minUsage = This->contextCache[i].usedcount;
5961             }
5962         }
5963         /* clean up the context (this doesn't work for ATI at the moment */
5964 #if 0
5965         glXDestroyContext(swapchain->display, dropContext->context);
5966         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5967 #endif
5968         FIXME("Leak\n");
5969         dropContext->Width = 0;
5970         dropContext->pSurface = pSurface;
5971         *context = dropContext;
5972     } else {
5973         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5974           for (i = 0; i < CONTEXT_CACHE; i++) {
5975              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5976           }
5977         }
5978     }
5979     if (*context != NULL)
5980         return WINED3D_OK;
5981     else
5982         return E_OUTOFMEMORY;
5983 }
5984 #endif
5985
5986 /* Reapply the device stateblock */
5987 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
5988
5989     BOOL oldRecording;  
5990     IWineD3DStateBlockImpl *oldUpdateStateBlock;
5991     DWORD i;
5992
5993     /* Disable recording */
5994     oldUpdateStateBlock = This->updateStateBlock;
5995     oldRecording= This->isRecordingState;
5996     This->isRecordingState = FALSE;
5997     This->updateStateBlock = This->stateBlock;
5998
5999     /* Reapply the state block */ 
6000     IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6001
6002     /* Temporaryily mark all render states dirty to force reapplication
6003      * until the context management for is integrated with the state management
6004      */
6005     for(i = 1; i < WINEHIGHEST_RENDER_STATE; i++) {
6006         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(i));
6007     }
6008
6009     /* Restore recording */
6010     This->isRecordingState = oldRecording;
6011     This->updateStateBlock = oldUpdateStateBlock;
6012 }
6013
6014 /* Set offscreen rendering. When rendering offscreen the surface will be
6015  * rendered upside down to compensate for the fact that D3D texture coordinates
6016  * are flipped compared to GL texture coordinates. The cullmode is affected by
6017  * this, so it must be updated. To update the cullmode stateblock recording has
6018  * to be temporarily disabled. The new state management code will hopefully
6019  * make this unnecessary */
6020 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
6021
6022     BOOL oldRecording;
6023     IWineD3DStateBlockImpl *oldUpdateStateBlock;
6024
6025     /* Nothing to update, return. */
6026     if (This->render_offscreen == isTexture) return;
6027
6028     /* Disable recording */
6029     oldUpdateStateBlock = This->updateStateBlock;
6030     oldRecording= This->isRecordingState;
6031     This->isRecordingState = FALSE;
6032     This->updateStateBlock = This->stateBlock;
6033
6034     This->render_offscreen = isTexture;
6035     if (This->depth_copy_state != WINED3D_DCS_NO_COPY) {
6036         This->depth_copy_state = WINED3D_DCS_COPY;
6037     }
6038     This->last_was_rhw = FALSE;
6039     This->proj_valid = FALSE;
6040     IWineD3DDeviceImpl_MarkStateDirty(This, WINED3DRS_CULLMODE);
6041
6042     /* Restore recording */
6043     This->isRecordingState = oldRecording;
6044     This->updateStateBlock = oldUpdateStateBlock;
6045 }
6046
6047 /* Returns an array of compatible FBconfig(s).
6048  * The array must be freed with XFree. Requires ENTER_GL() */
6049
6050 static GLXFBConfig* device_find_fbconfigs(
6051     IWineD3DDeviceImpl* This,
6052     IWineD3DSwapChainImpl* implicitSwapchainImpl,
6053     IWineD3DSurface* RenderSurface) {
6054
6055     GLXFBConfig* cfgs = NULL;
6056     int nCfgs = 0;
6057     int attribs[256];
6058     int nAttribs = 0;
6059
6060     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6061     WINED3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6062     WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6063
6064     /**TODO:
6065         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off, 
6066         it StencilSurface != NULL && zBufferTarget == NULL switch it on
6067     */
6068
6069 #define PUSH1(att)        attribs[nAttribs++] = (att);
6070 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6071
6072     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6073
6074     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6075     PUSH2(GLX_X_RENDERABLE,  TRUE);
6076     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
6077     TRACE("calling makeglcfg\n");
6078     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6079     PUSH1(None);
6080     TRACE("calling chooseFGConfig\n");
6081     cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
6082                              DefaultScreen(implicitSwapchainImpl->display),
6083                              attribs, &nCfgs);
6084     if (cfgs == NULL) {
6085         /* OK we didn't find the exact config, so use any reasonable match */
6086         /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
6087            why we failed. */
6088         static BOOL show_message = TRUE;
6089         if (show_message) {
6090             ERR("Failed to find exact match, finding alternative but you may "
6091                 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
6092             show_message = FALSE;
6093         }
6094         nAttribs = 0;
6095         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6096         /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
6097         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
6098         PUSH2(GLX_DOUBLEBUFFER, FALSE);
6099         TRACE("calling makeglcfg\n");
6100         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6101         PUSH1(None);
6102         cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
6103                                  DefaultScreen(implicitSwapchainImpl->display),
6104                                  attribs, &nCfgs);
6105     }
6106                                                                                                                                                                       
6107     if (cfgs == NULL) {
6108         ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
6109             BackBufferFormat, debug_d3dformat(BackBufferFormat),
6110             StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6111     } else {
6112 #ifdef EXTRA_TRACES
6113         int i;
6114         for (i = 0; i < nCfgs; ++i) {
6115             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6116             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6117             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6118         }
6119         if (NULL != This->renderTarget) {
6120             glFlush();
6121             vcheckGLcall("glFlush");
6122             /** This is only useful if the old render target was a swapchain,
6123             * we need to supercede this with a function that displays
6124             * the current buffer on the screen. This is easy to do in glx1.3 but
6125             * we need to do copy-write pixels in glx 1.2.
6126             ************************************************/
6127             glXSwapBuffers(implicitSwapChainImpl->display,
6128                            implicitSwapChainImpl->drawable);
6129             printf("Hit Enter to get next frame ...\n");
6130             getchar();
6131         }
6132 #endif
6133     }
6134 #undef PUSH1
6135 #undef PUSH2
6136
6137    return cfgs;
6138 }
6139
6140 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6141 * the functionality needs splitting up so that we don't do more than we should do.
6142 * this only seems to impact performance a little.
6143  ******************************/
6144 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6145                                                IWineD3DSurface *RenderSurface) {
6146
6147     /**
6148     * Currently only active for GLX >= 1.3
6149     * for others versions we'll have to use GLXPixmaps
6150     *
6151     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6152     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6153     * so only check OpenGL version
6154     * ..........................
6155     * I don't believe that it is a problem with NVidia headers,
6156     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6157     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6158     * ATI Note:
6159     * Your application will report GLX version 1.2 on glXQueryVersion.
6160     * However, it is safe to call the GLX 1.3 functions as described below.
6161     */
6162 #if defined(GL_VERSION_1_3)
6163
6164     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6165     GLXFBConfig* cfgs = NULL;
6166     IWineD3DSwapChain     *currentSwapchain;
6167     IWineD3DSwapChainImpl *currentSwapchainImpl;
6168     IWineD3DSwapChain     *implicitSwapchain;
6169     IWineD3DSwapChainImpl *implicitSwapchainImpl;
6170     IWineD3DSwapChain     *renderSurfaceSwapchain;
6171     IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
6172
6173     /* Obtain a reference to the device implicit swapchain,
6174      * the swapchain of the current render target,
6175      * and the swapchain of the new render target.
6176      * Fallback to device implicit swapchain if the current render target doesn't have one */
6177     IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
6178     IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
6179     IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DSwapChain, (void **)&currentSwapchain);
6180     if (currentSwapchain == NULL)
6181         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
6182
6183     currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
6184     implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
6185     renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
6186
6187     ENTER_GL();
6188
6189     /**
6190     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6191     *  renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
6192      **********************************************************************/
6193     if (renderSurfaceSwapchain != NULL) {
6194
6195         /* We also need to make sure that the lights &co are also in the context of the swapchains */
6196         /* FIXME: If the render target gets sent to the frontBuffer, should we be presenting it raw? */
6197         TRACE("making swapchain active\n");
6198         if (RenderSurface != This->render_targets[0]) {
6199             BOOL backbuf = FALSE;
6200             int i;
6201
6202             for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
6203                 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
6204                     backbuf = TRUE;
6205                     break;
6206                 }
6207             }
6208
6209             if (backbuf) {
6210             } else {
6211                 /* This could be flagged so that some operations work directly with the front buffer */
6212                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
6213             }
6214             if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
6215                                renderSurfaceSwapchainImpl->win,
6216                                renderSurfaceSwapchainImpl->glCtx) == False) {
6217
6218                 TRACE("Error in setting current context: context %p drawable %ld !\n",
6219                        implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
6220             }
6221             checkGLcall("glXMakeContextCurrent");
6222
6223             /* Clean up the old context */
6224             IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
6225
6226             /* Reapply the stateblock, and set the device not to render to texture */
6227             device_reapply_stateblock(This);
6228             device_render_to_texture(This, FALSE);
6229         }
6230
6231     /* Offscreen rendering: PBuffers (currently disabled).
6232      * Also note that this path is never reached if FBOs are supported */
6233     } else if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER &&
6234                (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
6235
6236         /** ********************************************************************
6237         * This is a quickly hacked out implementation of offscreen textures.
6238         * It will work in most cases but there may be problems if the client
6239         * modifies the texture directly, or expects the contents of the rendertarget
6240         * to be persistent.
6241         *
6242         * There are some real speed vs compatibility issues here:
6243         *    we should really use a new context for every texture, but that eats ram.
6244         *    we should also be restoring the texture to the pbuffer but that eats CPU
6245         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6246         *    but if this means reusing the display backbuffer then we need to make sure that
6247         *    states are correctly preserved.
6248         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6249         * and gain a good performance increase at the cost of compatibility.
6250         * I would suggest that, when this is the case, a user configurable flag be made
6251         * available, allowing the user to choose the best emulated experience for them.
6252          *********************************************************************/
6253
6254         XVisualInfo *visinfo;
6255         glContext   *newContext;
6256
6257         /* Here were using a shared context model */
6258         if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6259             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6260         }
6261
6262         /* If the context doesn't exist then create a new one */
6263         /* TODO: This should really be part of findGlContext */
6264         if (NULL == newContext->context) {
6265
6266             int attribs[256];
6267             int nAttribs = 0;
6268
6269             TRACE("making new buffer\n");
6270             attribs[nAttribs++] = GLX_PBUFFER_WIDTH; 
6271             attribs[nAttribs++] = newContext->Width;
6272             attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
6273             attribs[nAttribs++] = newContext->Height;
6274             attribs[nAttribs++] = None;
6275
6276             newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
6277
6278             /** ****************************************
6279             *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6280             *they note:
6281             *   In future releases, we may provide the calls glXCreateNewContext,
6282             *   glXQueryDrawable and glXMakeContextCurrent.
6283             *    so until then we have to use glXGetVisualFromFBConfig &co..
6284             ********************************************/
6285
6286             visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
6287             if (!visinfo) {
6288                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6289             } else {
6290                 newContext->context = glXCreateContext(
6291                     implicitSwapchainImpl->display, visinfo,
6292                     implicitSwapchainImpl->glCtx, GL_TRUE);
6293
6294                 XFree(visinfo);
6295             }
6296         }
6297         if (NULL == newContext || NULL == newContext->context) {
6298             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6299         } else {
6300             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6301             if (glXMakeCurrent(implicitSwapchainImpl->display,
6302                 newContext->drawable, newContext->context) == False) {
6303
6304                 TRACE("Error in setting current context: context %p drawable %ld\n",
6305                     newContext->context, newContext->drawable);
6306             }
6307             checkGLcall("glXMakeContextCurrent");
6308
6309             /* Clean up the old context */
6310             IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
6311
6312             /* Reapply stateblock, and set device to render to a texture */
6313             device_reapply_stateblock(This);
6314             device_render_to_texture(This, TRUE);
6315
6316             /* Set the current context of the swapchain to the new context */
6317             implicitSwapchainImpl->drawable   = newContext->drawable;
6318             implicitSwapchainImpl->render_ctx = newContext->context;
6319         }
6320     } else {
6321         /* Same context, but update render_offscreen and cull mode */
6322         device_render_to_texture(This, TRUE);
6323     }
6324
6325     if (cfgs != NULL)                   XFree(cfgs);
6326     if (implicitSwapchain != NULL)       IWineD3DSwapChain_Release(implicitSwapchain);
6327     if (currentSwapchain != NULL)       IWineD3DSwapChain_Release(currentSwapchain);
6328     if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
6329     LEAVE_GL();
6330 #endif
6331     return WINED3D_OK;
6332 }
6333
6334 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6335                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6336     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6337     /* TODO: the use of Impl is deprecated. */
6338     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6339
6340     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6341
6342     /* some basic validation checks */
6343     if(This->cursorTexture) {
6344         ENTER_GL();
6345         glDeleteTextures(1, &This->cursorTexture);
6346         LEAVE_GL();
6347         This->cursorTexture = 0;
6348     }
6349
6350     if(pCursorBitmap) {
6351         /* MSDN: Cursor must be A8R8G8B8 */
6352         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6353             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6354             return WINED3DERR_INVALIDCALL;
6355         }
6356
6357         /* MSDN: Cursor must be smaller than the display mode */
6358         if(pSur->currentDesc.Width > This->ddraw_width ||
6359            pSur->currentDesc.Height > This->ddraw_height) {
6360             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);
6361             return WINED3DERR_INVALIDCALL;
6362         }
6363
6364         /* TODO: MSDN: Cursor sizes must be a power of 2 */
6365         /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
6366          * Texture and Blitting code to draw the cursor
6367          */
6368         pSur->Flags |= SFLAG_FORCELOAD;
6369         IWineD3DSurface_PreLoad(pCursorBitmap);
6370         pSur->Flags &= ~SFLAG_FORCELOAD;
6371         /* Do not store the surface's pointer because the application may release
6372          * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
6373          * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
6374          */
6375         This->cursorTexture = pSur->glDescription.textureName;
6376         This->cursorWidth = pSur->currentDesc.Width;
6377         This->cursorHeight = pSur->currentDesc.Height;
6378         pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
6379     }
6380
6381     This->xHotSpot = XHotSpot;
6382     This->yHotSpot = YHotSpot;
6383     return WINED3D_OK;
6384 }
6385
6386 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6387     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6388     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6389
6390     This->xScreenSpace = XScreenSpace;
6391     This->yScreenSpace = YScreenSpace;
6392
6393     return;
6394
6395 }
6396
6397 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6398     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6399     BOOL oldVisible = This->bCursorVisible;
6400     TRACE("(%p) : visible(%d)\n", This, bShow);
6401
6402     if(This->cursorTexture)
6403         This->bCursorVisible = bShow;
6404
6405     return oldVisible;
6406 }
6407
6408 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6409     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6410     TRACE("(%p) : state (%u)\n", This, This->state);
6411     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6412     switch (This->state) {
6413     case WINED3D_OK:
6414         return WINED3D_OK;
6415     case WINED3DERR_DEVICELOST:
6416         {
6417             ResourceList *resourceList  = This->resources;
6418             while (NULL != resourceList) {
6419                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6420                 return WINED3DERR_DEVICENOTRESET;
6421                 resourceList = resourceList->next;
6422             }
6423             return WINED3DERR_DEVICELOST;
6424         }
6425     case WINED3DERR_DRIVERINTERNALERROR:
6426         return WINED3DERR_DRIVERINTERNALERROR;
6427     }
6428
6429     /* Unknown state */
6430     return WINED3DERR_DRIVERINTERNALERROR;
6431 }
6432
6433
6434 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6435     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6436     /** FIXME: Resource tracking needs to be done,
6437     * The closes we can do to this is set the priorities of all managed textures low
6438     * and then reset them.
6439      ***********************************************************/
6440     FIXME("(%p) : stub\n", This);
6441     return WINED3D_OK;
6442 }
6443
6444 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6445     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6446     if(surface->Flags & SFLAG_DIBSECTION) {
6447         /* Release the DC */
6448         SelectObject(surface->hDC, surface->dib.holdbitmap);
6449         DeleteDC(surface->hDC);
6450         /* Release the DIB section */
6451         DeleteObject(surface->dib.DIBsection);
6452         surface->dib.bitmap_data = NULL;
6453         surface->resource.allocatedMemory = NULL;
6454         surface->Flags &= ~SFLAG_DIBSECTION;
6455     }
6456     surface->currentDesc.Width = *pPresentationParameters->BackBufferWidth;
6457     surface->currentDesc.Height = *pPresentationParameters->BackBufferHeight;
6458     if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
6459         surface->pow2Width = *pPresentationParameters->BackBufferWidth;
6460         surface->pow2Height = *pPresentationParameters->BackBufferHeight;
6461     } else {
6462         surface->pow2Width = surface->pow2Height = 1;
6463         while (surface->pow2Width < *pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6464         while (surface->pow2Height < *pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6465     }
6466     if(surface->glDescription.textureName) {
6467         ENTER_GL();
6468         glDeleteTextures(1, &surface->glDescription.textureName);
6469         LEAVE_GL();
6470         surface->glDescription.textureName = 0;
6471     }
6472     if(surface->pow2Width != *pPresentationParameters->BackBufferWidth ||
6473        surface->pow2Height != *pPresentationParameters->BackBufferHeight) {
6474         surface->Flags |= SFLAG_NONPOW2;
6475     } else  {
6476         surface->Flags &= ~SFLAG_NONPOW2;
6477     }
6478     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
6479     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6480 }
6481
6482 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6483     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6484     IWineD3DSwapChainImpl *swapchain;
6485     HRESULT hr;
6486     BOOL DisplayModeChanged = FALSE;
6487     WINED3DDISPLAYMODE mode;
6488     TRACE("(%p)\n", This);
6489
6490     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6491     if(FAILED(hr)) {
6492         ERR("Failed to get the first implicit swapchain\n");
6493         return hr;
6494     }
6495
6496     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6497      * on an existing gl context, so there's no real need for recreation.
6498      *
6499      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6500      *
6501      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6502      */
6503     TRACE("New params:\n");
6504     TRACE("BackBufferWidth = %d\n", *pPresentationParameters->BackBufferWidth);
6505     TRACE("BackBufferHeight = %d\n", *pPresentationParameters->BackBufferHeight);
6506     TRACE("BackBufferFormat = %s\n", debug_d3dformat(*pPresentationParameters->BackBufferFormat));
6507     TRACE("BackBufferCount = %d\n", *pPresentationParameters->BackBufferCount);
6508     TRACE("MultiSampleType = %d\n", *pPresentationParameters->MultiSampleType);
6509     TRACE("MultiSampleQuality = %d\n", *pPresentationParameters->MultiSampleQuality);
6510     TRACE("SwapEffect = %d\n", *pPresentationParameters->SwapEffect);
6511     TRACE("hDeviceWindow = %p\n", *pPresentationParameters->hDeviceWindow);
6512     TRACE("Windowed = %s\n", *pPresentationParameters->Windowed ? "true" : "false");
6513     TRACE("EnableAutoDepthStencil = %s\n", *pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6514     TRACE("Flags = %08x\n", *pPresentationParameters->Flags);
6515     TRACE("FullScreen_RefreshRateInHz = %d\n", *pPresentationParameters->FullScreen_RefreshRateInHz);
6516     TRACE("PresentationInterval = %d\n", *pPresentationParameters->PresentationInterval);
6517
6518     /* No special treatment of these parameters. Just store them */
6519     swapchain->presentParms.SwapEffect = *pPresentationParameters->SwapEffect;
6520     swapchain->presentParms.Flags = *pPresentationParameters->Flags;
6521     swapchain->presentParms.PresentationInterval = *pPresentationParameters->PresentationInterval;
6522     swapchain->presentParms.FullScreen_RefreshRateInHz = *pPresentationParameters->FullScreen_RefreshRateInHz;
6523
6524     /* What to do about these? */
6525     if(*pPresentationParameters->BackBufferCount != 0 &&
6526         *pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6527         ERR("Cannot change the back buffer count yet\n");
6528     }
6529     if(*pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6530         *pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6531         ERR("Cannot change the back buffer format yet\n");
6532     }
6533     if(*pPresentationParameters->hDeviceWindow != NULL &&
6534         *pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6535         ERR("Cannot change the device window yet\n");
6536     }
6537     if(*pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
6538         ERR("What do do about a changed auto depth stencil parameter?\n");
6539     }
6540
6541     if(*pPresentationParameters->Windowed) {
6542         mode.Width = swapchain->orig_width;
6543         mode.Height = swapchain->orig_height;
6544         mode.RefreshRate = 0;
6545         mode.Format = swapchain->presentParms.BackBufferFormat;
6546     } else {
6547         mode.Width = *pPresentationParameters->BackBufferWidth;
6548         mode.Height = *pPresentationParameters->BackBufferHeight;
6549         mode.RefreshRate = *pPresentationParameters->FullScreen_RefreshRateInHz;
6550         mode.Format = swapchain->presentParms.BackBufferFormat;
6551     }
6552
6553     /* Should Width == 800 && Height == 0 set 800x600? */
6554     if(*pPresentationParameters->BackBufferWidth != 0 && *pPresentationParameters->BackBufferHeight != 0 &&
6555        (*pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6556         *pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6557     {
6558         WINED3DVIEWPORT vp;
6559         int i;
6560
6561         vp.X = 0;
6562         vp.Y = 0;
6563         vp.Width = *pPresentationParameters->BackBufferWidth;
6564         vp.Height = *pPresentationParameters->BackBufferHeight;
6565         vp.MinZ = 0;
6566         vp.MaxZ = 1;
6567
6568         if(!*pPresentationParameters->Windowed) {
6569             DisplayModeChanged = TRUE;
6570         }
6571         swapchain->presentParms.BackBufferWidth = *pPresentationParameters->BackBufferWidth;
6572         swapchain->presentParms.BackBufferHeight = *pPresentationParameters->BackBufferHeight;
6573
6574         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
6575         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
6576             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
6577         }
6578
6579         /* Now set the new viewport */
6580         IWineD3DDevice_SetViewport(iface, &vp);
6581     }
6582
6583     if((*pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
6584        (swapchain->presentParms.Windowed && !*pPresentationParameters->Windowed) ||
6585         DisplayModeChanged) {
6586         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6587     }
6588
6589     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6590     return WINED3D_OK;
6591 }
6592
6593 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6594     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6595     /** FIXME: always true at the moment **/
6596     if(!bEnableDialogs) {
6597         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6598     }
6599     return WINED3D_OK;
6600 }
6601
6602
6603 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6604     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6605     TRACE("(%p) : pParameters %p\n", This, pParameters);
6606
6607     *pParameters = This->createParms;
6608     return WINED3D_OK;
6609 }
6610
6611 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6612     IWineD3DSwapChain *swapchain;
6613     HRESULT hrc = WINED3D_OK;
6614
6615     TRACE("Relaying  to swapchain\n");
6616
6617     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6618         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6619         IWineD3DSwapChain_Release(swapchain);
6620     }
6621     return;
6622 }
6623
6624 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6625     IWineD3DSwapChain *swapchain;
6626     HRESULT hrc = WINED3D_OK;
6627
6628     TRACE("Relaying  to swapchain\n");
6629
6630     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6631         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6632         IWineD3DSwapChain_Release(swapchain);
6633     }
6634     return;
6635 }
6636
6637
6638 /** ********************************************************
6639 *   Notification functions
6640 ** ********************************************************/
6641 /** This function must be called in the release of a resource when ref == 0,
6642 * the contents of resource must still be correct,
6643 * any handels to other resource held by the caller must be closed
6644 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6645  *****************************************************/
6646 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6647     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6648     ResourceList* resourceList;
6649
6650     TRACE("(%p) : resource %p\n", This, resource);
6651 #if 0
6652     EnterCriticalSection(&resourceStoreCriticalSection);
6653 #endif
6654     /* add a new texture to the frot of the linked list */
6655     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6656     resourceList->resource = resource;
6657
6658     /* Get the old head */
6659     resourceList->next = This->resources;
6660
6661     This->resources = resourceList;
6662     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6663
6664 #if 0
6665     LeaveCriticalSection(&resourceStoreCriticalSection);
6666 #endif
6667     return;
6668 }
6669
6670 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6671     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6672     ResourceList* resourceList = NULL;
6673     ResourceList* previousResourceList = NULL;
6674     
6675     TRACE("(%p) : resource %p\n", This, resource);
6676
6677 #if 0
6678     EnterCriticalSection(&resourceStoreCriticalSection);
6679 #endif
6680     resourceList = This->resources;
6681
6682     while (resourceList != NULL) {
6683         if(resourceList->resource == resource) break;
6684         previousResourceList = resourceList;
6685         resourceList = resourceList->next;
6686     }
6687
6688     if (resourceList == NULL) {
6689         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6690 #if 0
6691         LeaveCriticalSection(&resourceStoreCriticalSection);
6692 #endif
6693         return;
6694     } else {
6695             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6696     }
6697     /* make sure we don't leave a hole in the list */
6698     if (previousResourceList != NULL) {
6699         previousResourceList->next = resourceList->next;
6700     } else {
6701         This->resources = resourceList->next;
6702     }
6703
6704 #if 0
6705     LeaveCriticalSection(&resourceStoreCriticalSection);
6706 #endif
6707     return;
6708 }
6709
6710
6711 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6712     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6713     int counter;
6714
6715     TRACE("(%p) : resource %p\n", This, resource);
6716     switch(IWineD3DResource_GetType(resource)){
6717         case WINED3DRTYPE_SURFACE:
6718         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6719         break;
6720         case WINED3DRTYPE_TEXTURE:
6721         case WINED3DRTYPE_CUBETEXTURE:
6722         case WINED3DRTYPE_VOLUMETEXTURE:
6723                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
6724                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6725                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6726                         This->stateBlock->textures[counter] = NULL;
6727                     }
6728                     if (This->updateStateBlock != This->stateBlock ){
6729                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6730                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6731                             This->updateStateBlock->textures[counter] = NULL;
6732                         }
6733                     }
6734                 }
6735         break;
6736         case WINED3DRTYPE_VOLUME:
6737         /* TODO: nothing really? */
6738         break;
6739         case WINED3DRTYPE_VERTEXBUFFER:
6740         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6741         {
6742             int streamNumber;
6743             TRACE("Cleaning up stream pointers\n");
6744
6745             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6746                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6747                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6748                 */
6749                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6750                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6751                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6752                         This->updateStateBlock->streamSource[streamNumber] = 0;
6753                         /* Set changed flag? */
6754                     }
6755                 }
6756                 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) */
6757                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6758                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6759                         This->stateBlock->streamSource[streamNumber] = 0;
6760                     }
6761                 }
6762 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6763                  else { /* This shouldn't happen */
6764                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6765                 }
6766 #endif
6767
6768             }
6769         }
6770         break;
6771         case WINED3DRTYPE_INDEXBUFFER:
6772         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6773         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6774             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6775                 This->updateStateBlock->pIndexData =  NULL;
6776             }
6777         }
6778         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6779             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6780                 This->stateBlock->pIndexData =  NULL;
6781             }
6782         }
6783
6784         break;
6785         default:
6786         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6787         break;
6788     }
6789
6790
6791     /* Remove the resoruce from the resourceStore */
6792     IWineD3DDeviceImpl_RemoveResource(iface, resource);
6793
6794     TRACE("Resource released\n");
6795
6796 }
6797
6798 /**********************************************************
6799  * IWineD3DDevice VTbl follows
6800  **********************************************************/
6801
6802 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6803 {
6804     /*** IUnknown methods ***/
6805     IWineD3DDeviceImpl_QueryInterface,
6806     IWineD3DDeviceImpl_AddRef,
6807     IWineD3DDeviceImpl_Release,
6808     /*** IWineD3DDevice methods ***/
6809     IWineD3DDeviceImpl_GetParent,
6810     /*** Creation methods**/
6811     IWineD3DDeviceImpl_CreateVertexBuffer,
6812     IWineD3DDeviceImpl_CreateIndexBuffer,
6813     IWineD3DDeviceImpl_CreateStateBlock,
6814     IWineD3DDeviceImpl_CreateSurface,
6815     IWineD3DDeviceImpl_CreateTexture,
6816     IWineD3DDeviceImpl_CreateVolumeTexture,
6817     IWineD3DDeviceImpl_CreateVolume,
6818     IWineD3DDeviceImpl_CreateCubeTexture,
6819     IWineD3DDeviceImpl_CreateQuery,
6820     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6821     IWineD3DDeviceImpl_CreateVertexDeclaration,
6822     IWineD3DDeviceImpl_CreateVertexShader,
6823     IWineD3DDeviceImpl_CreatePixelShader,
6824     IWineD3DDeviceImpl_CreatePalette,
6825     /*** Odd functions **/
6826     IWineD3DDeviceImpl_Init3D,
6827     IWineD3DDeviceImpl_Uninit3D,
6828     IWineD3DDeviceImpl_SetFullscreen,
6829     IWineD3DDeviceImpl_EnumDisplayModes,
6830     IWineD3DDeviceImpl_EvictManagedResources,
6831     IWineD3DDeviceImpl_GetAvailableTextureMem,
6832     IWineD3DDeviceImpl_GetBackBuffer,
6833     IWineD3DDeviceImpl_GetCreationParameters,
6834     IWineD3DDeviceImpl_GetDeviceCaps,
6835     IWineD3DDeviceImpl_GetDirect3D,
6836     IWineD3DDeviceImpl_GetDisplayMode,
6837     IWineD3DDeviceImpl_SetDisplayMode,
6838     IWineD3DDeviceImpl_GetHWND,
6839     IWineD3DDeviceImpl_SetHWND,
6840     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6841     IWineD3DDeviceImpl_GetRasterStatus,
6842     IWineD3DDeviceImpl_GetSwapChain,
6843     IWineD3DDeviceImpl_Reset,
6844     IWineD3DDeviceImpl_SetDialogBoxMode,
6845     IWineD3DDeviceImpl_SetCursorProperties,
6846     IWineD3DDeviceImpl_SetCursorPosition,
6847     IWineD3DDeviceImpl_ShowCursor,
6848     IWineD3DDeviceImpl_TestCooperativeLevel,
6849     /*** Getters and setters **/
6850     IWineD3DDeviceImpl_SetClipPlane,
6851     IWineD3DDeviceImpl_GetClipPlane,
6852     IWineD3DDeviceImpl_SetClipStatus,
6853     IWineD3DDeviceImpl_GetClipStatus,
6854     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6855     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6856     IWineD3DDeviceImpl_SetDepthStencilSurface,
6857     IWineD3DDeviceImpl_GetDepthStencilSurface,
6858     IWineD3DDeviceImpl_SetFVF,
6859     IWineD3DDeviceImpl_GetFVF,
6860     IWineD3DDeviceImpl_SetGammaRamp,
6861     IWineD3DDeviceImpl_GetGammaRamp,
6862     IWineD3DDeviceImpl_SetIndices,
6863     IWineD3DDeviceImpl_GetIndices,
6864     IWineD3DDeviceImpl_SetLight,
6865     IWineD3DDeviceImpl_GetLight,
6866     IWineD3DDeviceImpl_SetLightEnable,
6867     IWineD3DDeviceImpl_GetLightEnable,
6868     IWineD3DDeviceImpl_SetMaterial,
6869     IWineD3DDeviceImpl_GetMaterial,
6870     IWineD3DDeviceImpl_SetNPatchMode,
6871     IWineD3DDeviceImpl_GetNPatchMode,
6872     IWineD3DDeviceImpl_SetPaletteEntries,
6873     IWineD3DDeviceImpl_GetPaletteEntries,
6874     IWineD3DDeviceImpl_SetPixelShader,
6875     IWineD3DDeviceImpl_GetPixelShader,
6876     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6877     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6878     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6879     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6880     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6881     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6882     IWineD3DDeviceImpl_SetRenderState,
6883     IWineD3DDeviceImpl_GetRenderState,
6884     IWineD3DDeviceImpl_SetRenderTarget,
6885     IWineD3DDeviceImpl_GetRenderTarget,
6886     IWineD3DDeviceImpl_SetFrontBackBuffers,
6887     IWineD3DDeviceImpl_SetSamplerState,
6888     IWineD3DDeviceImpl_GetSamplerState,
6889     IWineD3DDeviceImpl_SetScissorRect,
6890     IWineD3DDeviceImpl_GetScissorRect,
6891     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6892     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6893     IWineD3DDeviceImpl_SetStreamSource,
6894     IWineD3DDeviceImpl_GetStreamSource,
6895     IWineD3DDeviceImpl_SetStreamSourceFreq,
6896     IWineD3DDeviceImpl_GetStreamSourceFreq,
6897     IWineD3DDeviceImpl_SetTexture,
6898     IWineD3DDeviceImpl_GetTexture,
6899     IWineD3DDeviceImpl_SetTextureStageState,
6900     IWineD3DDeviceImpl_GetTextureStageState,
6901     IWineD3DDeviceImpl_SetTransform,
6902     IWineD3DDeviceImpl_GetTransform,
6903     IWineD3DDeviceImpl_SetVertexDeclaration,
6904     IWineD3DDeviceImpl_GetVertexDeclaration,
6905     IWineD3DDeviceImpl_SetVertexShader,
6906     IWineD3DDeviceImpl_GetVertexShader,
6907     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6908     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6909     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6910     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6911     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6912     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6913     IWineD3DDeviceImpl_SetViewport,
6914     IWineD3DDeviceImpl_GetViewport,
6915     IWineD3DDeviceImpl_MultiplyTransform,
6916     IWineD3DDeviceImpl_ValidateDevice,
6917     IWineD3DDeviceImpl_ProcessVertices,
6918     /*** State block ***/
6919     IWineD3DDeviceImpl_BeginStateBlock,
6920     IWineD3DDeviceImpl_EndStateBlock,
6921     /*** Scene management ***/
6922     IWineD3DDeviceImpl_BeginScene,
6923     IWineD3DDeviceImpl_EndScene,
6924     IWineD3DDeviceImpl_Present,
6925     IWineD3DDeviceImpl_Clear,
6926     /*** Drawing ***/
6927     IWineD3DDeviceImpl_DrawPrimitive,
6928     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6929     IWineD3DDeviceImpl_DrawPrimitiveUP,
6930     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6931     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6932     IWineD3DDeviceImpl_DrawRectPatch,
6933     IWineD3DDeviceImpl_DrawTriPatch,
6934     IWineD3DDeviceImpl_DeletePatch,
6935     IWineD3DDeviceImpl_ColorFill,
6936     IWineD3DDeviceImpl_UpdateTexture,
6937     IWineD3DDeviceImpl_UpdateSurface,
6938     IWineD3DDeviceImpl_StretchRect,
6939     IWineD3DDeviceImpl_GetRenderTargetData,
6940     IWineD3DDeviceImpl_GetFrontBufferData,
6941     /*** Internal use IWineD3DDevice methods ***/
6942     IWineD3DDeviceImpl_SetupTextureStates,
6943     /*** object tracking ***/
6944     IWineD3DDeviceImpl_ResourceReleased
6945 };
6946
6947
6948 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6949     WINED3DRS_ALPHABLENDENABLE   ,
6950     WINED3DRS_ALPHAFUNC          ,
6951     WINED3DRS_ALPHAREF           ,
6952     WINED3DRS_ALPHATESTENABLE    ,
6953     WINED3DRS_BLENDOP            ,
6954     WINED3DRS_COLORWRITEENABLE   ,
6955     WINED3DRS_DESTBLEND          ,
6956     WINED3DRS_DITHERENABLE       ,
6957     WINED3DRS_FILLMODE           ,
6958     WINED3DRS_FOGDENSITY         ,
6959     WINED3DRS_FOGEND             ,
6960     WINED3DRS_FOGSTART           ,
6961     WINED3DRS_LASTPIXEL          ,
6962     WINED3DRS_SHADEMODE          ,
6963     WINED3DRS_SRCBLEND           ,
6964     WINED3DRS_STENCILENABLE      ,
6965     WINED3DRS_STENCILFAIL        ,
6966     WINED3DRS_STENCILFUNC        ,
6967     WINED3DRS_STENCILMASK        ,
6968     WINED3DRS_STENCILPASS        ,
6969     WINED3DRS_STENCILREF         ,
6970     WINED3DRS_STENCILWRITEMASK   ,
6971     WINED3DRS_STENCILZFAIL       ,
6972     WINED3DRS_TEXTUREFACTOR      ,
6973     WINED3DRS_WRAP0              ,
6974     WINED3DRS_WRAP1              ,
6975     WINED3DRS_WRAP2              ,
6976     WINED3DRS_WRAP3              ,
6977     WINED3DRS_WRAP4              ,
6978     WINED3DRS_WRAP5              ,
6979     WINED3DRS_WRAP6              ,
6980     WINED3DRS_WRAP7              ,
6981     WINED3DRS_ZENABLE            ,
6982     WINED3DRS_ZFUNC              ,
6983     WINED3DRS_ZWRITEENABLE
6984 };
6985
6986 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6987     WINED3DTSS_ADDRESSW              ,
6988     WINED3DTSS_ALPHAARG0             ,
6989     WINED3DTSS_ALPHAARG1             ,
6990     WINED3DTSS_ALPHAARG2             ,
6991     WINED3DTSS_ALPHAOP               ,
6992     WINED3DTSS_BUMPENVLOFFSET        ,
6993     WINED3DTSS_BUMPENVLSCALE         ,
6994     WINED3DTSS_BUMPENVMAT00          ,
6995     WINED3DTSS_BUMPENVMAT01          ,
6996     WINED3DTSS_BUMPENVMAT10          ,
6997     WINED3DTSS_BUMPENVMAT11          ,
6998     WINED3DTSS_COLORARG0             ,
6999     WINED3DTSS_COLORARG1             ,
7000     WINED3DTSS_COLORARG2             ,
7001     WINED3DTSS_COLOROP               ,
7002     WINED3DTSS_RESULTARG             ,
7003     WINED3DTSS_TEXCOORDINDEX         ,
7004     WINED3DTSS_TEXTURETRANSFORMFLAGS
7005 };
7006
7007 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7008     WINED3DSAMP_ADDRESSU         ,
7009     WINED3DSAMP_ADDRESSV         ,
7010     WINED3DSAMP_ADDRESSW         ,
7011     WINED3DSAMP_BORDERCOLOR      ,
7012     WINED3DSAMP_MAGFILTER        ,
7013     WINED3DSAMP_MINFILTER        ,
7014     WINED3DSAMP_MIPFILTER        ,
7015     WINED3DSAMP_MIPMAPLODBIAS    ,
7016     WINED3DSAMP_MAXMIPLEVEL      ,
7017     WINED3DSAMP_MAXANISOTROPY    ,
7018     WINED3DSAMP_SRGBTEXTURE      ,
7019     WINED3DSAMP_ELEMENTINDEX
7020 };
7021
7022 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7023     WINED3DRS_AMBIENT                       ,
7024     WINED3DRS_AMBIENTMATERIALSOURCE         ,
7025     WINED3DRS_CLIPPING                      ,
7026     WINED3DRS_CLIPPLANEENABLE               ,
7027     WINED3DRS_COLORVERTEX                   ,
7028     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
7029     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
7030     WINED3DRS_FOGDENSITY                    ,
7031     WINED3DRS_FOGEND                        ,
7032     WINED3DRS_FOGSTART                      ,
7033     WINED3DRS_FOGTABLEMODE                  ,
7034     WINED3DRS_FOGVERTEXMODE                 ,
7035     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
7036     WINED3DRS_LIGHTING                      ,
7037     WINED3DRS_LOCALVIEWER                   ,
7038     WINED3DRS_MULTISAMPLEANTIALIAS          ,
7039     WINED3DRS_MULTISAMPLEMASK               ,
7040     WINED3DRS_NORMALIZENORMALS              ,
7041     WINED3DRS_PATCHEDGESTYLE                ,
7042     WINED3DRS_POINTSCALE_A                  ,
7043     WINED3DRS_POINTSCALE_B                  ,
7044     WINED3DRS_POINTSCALE_C                  ,
7045     WINED3DRS_POINTSCALEENABLE              ,
7046     WINED3DRS_POINTSIZE                     ,
7047     WINED3DRS_POINTSIZE_MAX                 ,
7048     WINED3DRS_POINTSIZE_MIN                 ,
7049     WINED3DRS_POINTSPRITEENABLE             ,
7050     WINED3DRS_RANGEFOGENABLE                ,
7051     WINED3DRS_SPECULARMATERIALSOURCE        ,
7052     WINED3DRS_TWEENFACTOR                   ,
7053     WINED3DRS_VERTEXBLEND
7054 };
7055
7056 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7057     WINED3DTSS_TEXCOORDINDEX         ,
7058     WINED3DTSS_TEXTURETRANSFORMFLAGS
7059 };
7060
7061 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7062     WINED3DSAMP_DMAPOFFSET
7063 };
7064
7065 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
7066     DWORD rep = StateTable[state].representative;
7067     DWORD idx;
7068     BYTE shift;
7069
7070     if(!rep || isStateDirty(This, rep)) return;
7071
7072     This->dirtyArray[This->numDirtyEntries++] = rep;
7073     idx = rep >> 5;
7074     shift = rep & 0x1f;
7075     This->isStateDirty[idx] |= (1 << shift);
7076 }