wined3d: Add empty texture stage states 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     }
3688
3689     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3690     /**
3691      * TODO: merge HAL shaders context switching from prototype
3692      */
3693     return WINED3D_OK;
3694 }
3695
3696 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3697     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3698
3699     if (NULL == ppShader) {
3700         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3701         return WINED3DERR_INVALIDCALL;
3702     }
3703
3704     *ppShader =  This->stateBlock->pixelShader;
3705     if (NULL != *ppShader) {
3706         IWineD3DPixelShader_AddRef(*ppShader);
3707     }
3708     TRACE("(%p) : returning %p\n", This, *ppShader);
3709     return WINED3D_OK;
3710 }
3711
3712 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3713     IWineD3DDevice *iface,
3714     UINT start,
3715     CONST BOOL *srcData,
3716     UINT count) {
3717
3718     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3719     int i, cnt = min(count, MAX_CONST_B - start);
3720
3721     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3722             iface, srcData, start, count);
3723
3724     if (srcData == NULL || cnt < 0)
3725         return WINED3DERR_INVALIDCALL;
3726
3727     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3728     for (i = 0; i < cnt; i++)
3729         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3730
3731     for (i = start; i < cnt + start; ++i) {
3732         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3733         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
3734     }
3735
3736     return WINED3D_OK;
3737 }
3738
3739 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3740     IWineD3DDevice *iface,
3741     UINT start,
3742     BOOL *dstData,
3743     UINT count) {
3744
3745     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3746     int cnt = min(count, MAX_CONST_B - start);
3747
3748     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3749             iface, dstData, start, count);
3750
3751     if (dstData == NULL || cnt < 0)
3752         return WINED3DERR_INVALIDCALL;
3753
3754     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3755     return WINED3D_OK;
3756 }
3757
3758 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3759     IWineD3DDevice *iface,
3760     UINT start,
3761     CONST int *srcData,
3762     UINT count) {
3763
3764     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3765     int i, cnt = min(count, MAX_CONST_I - start);
3766
3767     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3768             iface, srcData, start, count);
3769
3770     if (srcData == NULL || cnt < 0)
3771         return WINED3DERR_INVALIDCALL;
3772
3773     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3774     for (i = 0; i < cnt; i++)
3775         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3776            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3777
3778     for (i = start; i < cnt + start; ++i) {
3779         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3780         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
3781     }
3782
3783     return WINED3D_OK;
3784 }
3785
3786 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3787     IWineD3DDevice *iface,
3788     UINT start,
3789     int *dstData,
3790     UINT count) {
3791
3792     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3793     int cnt = min(count, MAX_CONST_I - start);
3794
3795     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3796             iface, dstData, start, count);
3797
3798     if (dstData == NULL || cnt < 0)
3799         return WINED3DERR_INVALIDCALL;
3800
3801     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3802     return WINED3D_OK;
3803 }
3804
3805 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3806     IWineD3DDevice *iface,
3807     UINT start,
3808     CONST float *srcData,
3809     UINT count) {
3810
3811     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3812     int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3813
3814     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3815             iface, srcData, start, count);
3816
3817     if (srcData == NULL || cnt < 0)
3818         return WINED3DERR_INVALIDCALL;
3819
3820     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
3821     for (i = 0; i < cnt; i++)
3822         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3823            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3824
3825     for (i = start; i < cnt + start; ++i) {
3826         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3827             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3828             ptr->idx = i;
3829             list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3830             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3831         }
3832         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3833     }
3834
3835     return WINED3D_OK;
3836 }
3837
3838 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3839     IWineD3DDevice *iface,
3840     UINT start,
3841     float *dstData,
3842     UINT count) {
3843
3844     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3845     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3846
3847     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3848             iface, dstData, start, count);
3849
3850     if (dstData == NULL || cnt < 0)
3851         return WINED3DERR_INVALIDCALL;
3852
3853     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3854     return WINED3D_OK;
3855 }
3856
3857 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3858 static HRESULT
3859 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3860     char *dest_ptr, *dest_conv = NULL;
3861     unsigned int i;
3862     DWORD DestFVF = dest->fvf;
3863     WINED3DVIEWPORT vp;
3864     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3865     BOOL doClip;
3866     int numTextures;
3867
3868     if (SrcFVF & WINED3DFVF_NORMAL) {
3869         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3870     }
3871
3872     if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
3873         ERR("Source has no position mask\n");
3874         return WINED3DERR_INVALIDCALL;
3875     }
3876
3877     /* We might access VBOs from this code, so hold the lock */
3878     ENTER_GL();
3879
3880     if (dest->resource.allocatedMemory == NULL) {
3881         /* This may happen if we do direct locking into a vbo. Unlikely,
3882          * but theoretically possible(ddraw processvertices test)
3883          */
3884         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3885         if(!dest->resource.allocatedMemory) {
3886             LEAVE_GL();
3887             ERR("Out of memory\n");
3888             return E_OUTOFMEMORY;
3889         }
3890         if(dest->vbo) {
3891             void *src;
3892             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3893             checkGLcall("glBindBufferARB");
3894             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3895             if(src) {
3896                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3897             }
3898             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3899             checkGLcall("glUnmapBufferARB");
3900         }
3901     }
3902
3903     /* Get a pointer into the destination vbo(create one if none exists) and
3904      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3905      */
3906     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3907         CreateVBO(dest);
3908     }
3909
3910     if(dest->vbo) {
3911         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3912         dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
3913         if(!dest_conv) {
3914             ERR("glMapBuffer failed\n");
3915             /* Continue without storing converted vertices */
3916         }
3917     }
3918
3919     /* Should I clip?
3920      * a) WINED3DRS_CLIPPING is enabled
3921      * b) WINED3DVOP_CLIP is passed
3922      */
3923     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3924         static BOOL warned = FALSE;
3925         /*
3926          * The clipping code is not quite correct. Some things need
3927          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3928          * so disable clipping for now.
3929          * (The graphics in Half-Life are broken, and my processvertices
3930          *  test crashes with IDirect3DDevice3)
3931         doClip = TRUE;
3932          */
3933         doClip = FALSE;
3934         if(!warned) {
3935            warned = TRUE;
3936            FIXME("Clipping is broken and disabled for now\n");
3937         }
3938     } else doClip = FALSE;
3939     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3940     if(dest_conv) {
3941         dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3942     }
3943
3944     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3945                                  WINED3DTS_VIEW,
3946                                  &view_mat);
3947     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3948                                  WINED3DTS_PROJECTION,
3949                                  &proj_mat);
3950     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3951                                  WINED3DTS_WORLDMATRIX(0),
3952                                  &world_mat);
3953
3954     TRACE("View mat:\n");
3955     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); \
3956     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); \
3957     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); \
3958     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); \
3959
3960     TRACE("Proj mat:\n");
3961     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); \
3962     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); \
3963     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); \
3964     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); \
3965
3966     TRACE("World mat:\n");
3967     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); \
3968     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); \
3969     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); \
3970     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); \
3971
3972     /* Get the viewport */
3973     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3974     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3975           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3976
3977     multiply_matrix(&mat,&view_mat,&world_mat);
3978     multiply_matrix(&mat,&proj_mat,&mat);
3979
3980     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3981
3982     for (i = 0; i < dwCount; i+= 1) {
3983         unsigned int tex_index;
3984
3985         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3986              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3987             /* The position first */
3988             float *p =
3989               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3990             float x, y, z, rhw;
3991             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3992
3993             /* Multiplication with world, view and projection matrix */
3994             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);
3995             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);
3996             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);
3997             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);
3998
3999             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4000
4001             /* WARNING: The following things are taken from d3d7 and were not yet checked
4002              * against d3d8 or d3d9!
4003              */
4004
4005             /* Clipping conditions: From
4006              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4007              *
4008              * A vertex is clipped if it does not match the following requirements
4009              * -rhw < x <= rhw
4010              * -rhw < y <= rhw
4011              *    0 < z <= rhw
4012              *    0 < rhw ( Not in d3d7, but tested in d3d7)
4013              *
4014              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4015              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4016              *
4017              */
4018
4019             if( !doClip ||
4020                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4021                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
4022                   ( rhw > eps ) ) ) {
4023
4024                 /* "Normal" viewport transformation (not clipped)
4025                  * 1) The values are divided by rhw
4026                  * 2) The y axis is negative, so multiply it with -1
4027                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4028                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4029                  * 4) Multiply x with Width/2 and add Width/2
4030                  * 5) The same for the height
4031                  * 6) Add the viewpoint X and Y to the 2D coordinates and
4032                  *    The minimum Z value to z
4033                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4034                  *
4035                  * Well, basically it's simply a linear transformation into viewport
4036                  * coordinates
4037                  */
4038
4039                 x /= rhw;
4040                 y /= rhw;
4041                 z /= rhw;
4042
4043                 y *= -1;
4044
4045                 x *= vp.Width / 2;
4046                 y *= vp.Height / 2;
4047                 z *= vp.MaxZ - vp.MinZ;
4048
4049                 x += vp.Width / 2 + vp.X;
4050                 y += vp.Height / 2 + vp.Y;
4051                 z += vp.MinZ;
4052
4053                 rhw = 1 / rhw;
4054             } else {
4055                 /* That vertex got clipped
4056                  * Contrary to OpenGL it is not dropped completely, it just
4057                  * undergoes a different calculation.
4058                  */
4059                 TRACE("Vertex got clipped\n");
4060                 x += rhw;
4061                 y += rhw;
4062
4063                 x  /= 2;
4064                 y  /= 2;
4065
4066                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
4067                  * outside of the main vertex buffer memory. That needs some more
4068                  * investigation...
4069                  */
4070             }
4071
4072             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
4073
4074
4075             ( (float *) dest_ptr)[0] = x;
4076             ( (float *) dest_ptr)[1] = y;
4077             ( (float *) dest_ptr)[2] = z;
4078             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
4079
4080             dest_ptr += 3 * sizeof(float);
4081
4082             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4083                 dest_ptr += sizeof(float);
4084             }
4085
4086             if(dest_conv) {
4087                 float w = 1 / rhw;
4088                 ( (float *) dest_conv)[0] = x * w;
4089                 ( (float *) dest_conv)[1] = y * w;
4090                 ( (float *) dest_conv)[2] = z * w;
4091                 ( (float *) dest_conv)[3] = w;
4092
4093                 dest_conv += 3 * sizeof(float);
4094
4095                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4096                     dest_conv += sizeof(float);
4097                 }
4098             }
4099         }
4100         if (DestFVF & WINED3DFVF_PSIZE) {
4101             dest_ptr += sizeof(DWORD);
4102             if(dest_conv) dest_conv += sizeof(DWORD);
4103         }
4104         if (DestFVF & WINED3DFVF_NORMAL) {
4105             float *normal =
4106               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
4107             /* AFAIK this should go into the lighting information */
4108             FIXME("Didn't expect the destination to have a normal\n");
4109             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4110             if(dest_conv) {
4111                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
4112             }
4113         }
4114
4115         if (DestFVF & WINED3DFVF_DIFFUSE) {
4116             DWORD *color_d = 
4117               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
4118             if(!color_d) {
4119                 static BOOL warned = FALSE;
4120
4121                 if(!warned) {
4122                     ERR("No diffuse color in source, but destination has one\n");
4123                     warned = TRUE;
4124                 }
4125
4126                 *( (DWORD *) dest_ptr) = 0xffffffff;
4127                 dest_ptr += sizeof(DWORD);
4128
4129                 if(dest_conv) {
4130                     *( (DWORD *) dest_conv) = 0xffffffff;
4131                     dest_conv += sizeof(DWORD);
4132                 }
4133             }
4134             else {
4135                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4136                 if(dest_conv) {
4137                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
4138                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
4139                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
4140                     dest_conv += sizeof(DWORD);
4141                 }
4142             }
4143         }
4144
4145         if (DestFVF & WINED3DFVF_SPECULAR) { 
4146             /* What's the color value in the feedback buffer? */
4147             DWORD *color_s = 
4148               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
4149             if(!color_s) {
4150                 static BOOL warned = FALSE;
4151
4152                 if(!warned) {
4153                     ERR("No specular color in source, but destination has one\n");
4154                     warned = TRUE;
4155                 }
4156
4157                 *( (DWORD *) dest_ptr) = 0xFF000000;
4158                 dest_ptr += sizeof(DWORD);
4159
4160                 if(dest_conv) {
4161                     *( (DWORD *) dest_conv) = 0xFF000000;
4162                     dest_conv += sizeof(DWORD);
4163                 }
4164             }
4165             else {
4166                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4167                 if(dest_conv) {
4168                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
4169                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
4170                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
4171                     dest_conv += sizeof(DWORD);
4172                 }
4173             }
4174         }
4175
4176         for (tex_index = 0; tex_index < numTextures; tex_index++) {
4177             float *tex_coord =
4178               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
4179                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
4180             if(!tex_coord) {
4181                 ERR("No source texture, but destination requests one\n");
4182                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4183                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4184             }
4185             else {
4186                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4187                 if(dest_conv) {
4188                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4189                 }
4190             }
4191         }
4192     }
4193
4194     if(dest_conv) {
4195         GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4196         checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
4197     }
4198
4199     LEAVE_GL();
4200
4201     return WINED3D_OK;
4202 }
4203 #undef copy_and_next
4204
4205 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4206     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4207     IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
4208     WineDirect3DVertexStridedData strided;
4209     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4210
4211     if (!SrcImpl) {
4212         WARN("NULL source vertex buffer\n");
4213         return WINED3DERR_INVALIDCALL;
4214     }
4215     /* We don't need the source vbo because this buffer is only used as
4216      * a source for ProcessVertices. Avoid wasting resources by converting the
4217      * buffer and loading the VBO
4218      */
4219     if(SrcImpl->vbo) {
4220         TRACE("Releasing the source vbo, it won't be needed\n");
4221
4222         if(!SrcImpl->resource.allocatedMemory) {
4223             /* Rescue the data from the buffer */
4224             void *src;
4225             SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
4226             if(!SrcImpl->resource.allocatedMemory) {
4227                 ERR("Out of memory\n");
4228                 return E_OUTOFMEMORY;
4229             }
4230
4231             ENTER_GL();
4232             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
4233             checkGLcall("glBindBufferARB");
4234
4235             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
4236             if(src) {
4237                 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
4238             }
4239
4240             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4241             checkGLcall("glUnmapBufferARB");
4242         } else {
4243             ENTER_GL();
4244         }
4245
4246         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
4247         checkGLcall("glBindBufferARB");
4248         GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
4249         checkGLcall("glDeleteBuffersARB");
4250         LEAVE_GL();
4251
4252         SrcImpl->vbo = 0;
4253     }
4254
4255     memset(&strided, 0, sizeof(strided));
4256     primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
4257
4258     return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4259 }
4260
4261 /*****
4262  * Apply / Get / Set Texture Stage States
4263  * TODO: Verify against dx9 definitions
4264  *****/
4265
4266 /* 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 */
4267 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
4268     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4269     DWORD Value = This->updateStateBlock->textureState[Stage][Type];
4270     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4271
4272     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4273
4274     /* Check that the stage is within limits  */
4275     if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
4276         TRACE("Attempt to access invalid texture rejected\n");
4277         return;
4278     }
4279
4280     ENTER_GL();
4281
4282     switch (Type) {
4283     case WINED3DTSS_ALPHAOP               :
4284     case WINED3DTSS_COLOROP               :
4285         /* nothing to do as moved to drawprim for now */
4286         break;
4287     case WINED3DTSS_ADDRESSW              :
4288 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4289             if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
4290                 FIXME("Unrecognized or unsupported WINED3DTADDRESS_* value %d, state %d\n", Value, Type);
4291
4292             } else {
4293                 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
4294                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
4295                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
4296                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4297             }
4298 #endif
4299     case WINED3DTSS_TEXCOORDINDEX         :
4300         {
4301             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4302
4303             /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4304                   one flag, you can still specify an index value, which the system uses to
4305                   determine the texture wrapping mode.
4306                   eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4307                   means use the vertex position (camera-space) as the input texture coordinates
4308                   for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4309                   state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
4310                   to the TEXCOORDINDEX value */
4311
4312             /**
4313              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4314              */
4315             switch (Value & 0xFFFF0000) {
4316             case WINED3DTSS_TCI_PASSTHRU:
4317                 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
4318                 glDisable(GL_TEXTURE_GEN_S);
4319                 glDisable(GL_TEXTURE_GEN_T);
4320                 glDisable(GL_TEXTURE_GEN_R);
4321                 glDisable(GL_TEXTURE_GEN_Q);
4322                 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
4323                 break;
4324
4325             case WINED3DTSS_TCI_CAMERASPACEPOSITION:
4326                 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4327                     as the input texture coordinates for this stage's texture transformation. This
4328                     equates roughly to EYE_LINEAR                                                  */
4329                 {
4330                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4331                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4332                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4333                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4334                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4335     
4336                     glMatrixMode(GL_MODELVIEW);
4337                     glPushMatrix();
4338                     glLoadIdentity();
4339                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4340                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4341                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4342                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4343                     glPopMatrix();
4344     
4345                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4346                     glEnable(GL_TEXTURE_GEN_S);
4347                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4348                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4349                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4350                     glEnable(GL_TEXTURE_GEN_T);
4351                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4352                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4353                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4354                     glEnable(GL_TEXTURE_GEN_R);
4355                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4356                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4357                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4358                 }
4359                 break;
4360
4361             case WINED3DTSS_TCI_CAMERASPACENORMAL:
4362                 {
4363                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4364                         float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4365                         float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4366                         float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4367                         float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4368                         TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
4369         
4370                         glMatrixMode(GL_MODELVIEW);
4371                         glPushMatrix();
4372                         glLoadIdentity();
4373                         glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4374                         glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4375                         glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4376                         glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4377                         glPopMatrix();
4378         
4379                         glEnable(GL_TEXTURE_GEN_S);
4380                         checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4381                         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4382                         checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4383                         glEnable(GL_TEXTURE_GEN_T);
4384                         checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4385                         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4386                         checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4387                         glEnable(GL_TEXTURE_GEN_R);
4388                         checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4389                         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4390                         checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4391                     }
4392                 }
4393                 break;
4394
4395             case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4396                 {
4397                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4398                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4399                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4400                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4401                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4402                     TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
4403     
4404                     glMatrixMode(GL_MODELVIEW);
4405                     glPushMatrix();
4406                     glLoadIdentity();
4407                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4408                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4409                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4410                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4411                     glPopMatrix();
4412     
4413                     glEnable(GL_TEXTURE_GEN_S);
4414                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4415                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4416                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4417                     glEnable(GL_TEXTURE_GEN_T);
4418                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4419                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4420                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4421                     glEnable(GL_TEXTURE_GEN_R);
4422                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4423                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4424                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4425                     }
4426                 }
4427                 break;
4428
4429             /* Unhandled types: */
4430             default:
4431                 /* Todo: */
4432                 /* ? disable GL_TEXTURE_GEN_n ? */
4433                 glDisable(GL_TEXTURE_GEN_S);
4434                 glDisable(GL_TEXTURE_GEN_T);
4435                 glDisable(GL_TEXTURE_GEN_R);
4436                 glDisable(GL_TEXTURE_GEN_Q);
4437                 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", Value);
4438                 break;
4439             }
4440         }
4441         break;
4442
4443         /* Unhandled */
4444     case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4445         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);
4446         break;
4447
4448     case WINED3DTSS_BUMPENVMAT00          :
4449     case WINED3DTSS_BUMPENVMAT01          :
4450         TRACE("BUMPENVMAT0%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4451         break;
4452     case WINED3DTSS_BUMPENVMAT10          :
4453     case WINED3DTSS_BUMPENVMAT11          :
4454         TRACE("BUMPENVMAT1%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4455         break;
4456
4457     case WINED3DTSS_BUMPENVLSCALE         :
4458       TRACE("BUMPENVLSCALE Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
4459       break;
4460
4461     case WINED3DTSS_BUMPENVLOFFSET        :
4462       TRACE("BUMPENVLOFFSET Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
4463       break;
4464
4465     case WINED3DTSS_RESULTARG             :
4466       TRACE("RESULTARG Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
4467       break;
4468
4469     default:
4470         /* Put back later: FIXME("(%p) : stub, Stage=%d, Type=%d, Value =%d\n", This, Stage, Type, Value); */
4471         TRACE("Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
4472     }
4473
4474     LEAVE_GL();
4475
4476     return;
4477 }
4478
4479 /*****
4480  * Get / Set Texture Stage States
4481  * TODO: Verify against dx9 definitions
4482  *****/
4483 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4484     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4485
4486     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4487
4488     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4489
4490     /* Reject invalid texture units */
4491     if (Stage >= GL_LIMITS(texture_stages)) {
4492         TRACE("Attempt to access invalid texture rejected\n");
4493         return WINED3DERR_INVALIDCALL;
4494     }
4495
4496     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4497     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
4498     This->updateStateBlock->textureState[Stage][Type]         = Value;
4499
4500     return WINED3D_OK;
4501 }
4502
4503 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4504     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4505     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4506     *pValue = This->updateStateBlock->textureState[Stage][Type];
4507     return WINED3D_OK;
4508 }
4509
4510 /*****
4511  * Get / Set Texture
4512  *****/
4513 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4514
4515     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4516     IWineD3DBaseTexture   *oldTexture;
4517
4518     oldTexture = This->updateStateBlock->textures[Stage];
4519     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
4520
4521 #if 0 /* TODO: check so vertex textures */
4522     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4523         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4524         return WINED3D_OK;
4525     }
4526 #endif
4527
4528     /* Reject invalid texture units */
4529     if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
4530         WARN("Attempt to access invalid texture rejected\n");
4531         return WINED3DERR_INVALIDCALL;
4532     }
4533
4534     if(pTexture != NULL) {
4535         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
4536          */
4537         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
4538             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4539             return WINED3DERR_INVALIDCALL;
4540         }
4541     }
4542
4543     oldTexture = This->updateStateBlock->textures[Stage];
4544     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
4545     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4546
4547     This->updateStateBlock->set.textures[Stage]     = TRUE;
4548     This->updateStateBlock->changed.textures[Stage] = TRUE;
4549     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4550     This->updateStateBlock->textures[Stage]         = pTexture;
4551
4552     /* Handle recording of state blocks */
4553     if (This->isRecordingState) {
4554         TRACE("Recording... not performing anything\n");
4555         return WINED3D_OK;
4556     }
4557
4558     /** NOTE: MSDN says that setTexture increases the reference count,
4559     * and the the application nust set the texture back to null (or have a leaky application),
4560     * This means we should pass the refcount up to the parent
4561      *******************************/
4562     if (NULL != This->updateStateBlock->textures[Stage]) {
4563         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4564     }
4565
4566     if (NULL != oldTexture) {
4567         IWineD3DBaseTexture_Release(oldTexture);
4568     }
4569
4570     /* Color keying is affected by the texture. Temporarily mark the color key state (=alpha test)
4571      * dirty until textures are integrated with the state management
4572      */
4573     if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
4574         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORKEYENABLE));
4575     }
4576
4577     return WINED3D_OK;
4578 }
4579
4580 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4581     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4582     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4583
4584     /* Reject invalid texture units */
4585     if (Stage >= GL_LIMITS(sampler_stages)) {
4586         TRACE("Attempt to access invalid texture rejected\n");
4587         return WINED3DERR_INVALIDCALL;
4588     }
4589     *ppTexture=This->stateBlock->textures[Stage];
4590     if (*ppTexture)
4591         IWineD3DBaseTexture_AddRef(*ppTexture);
4592
4593     return WINED3D_OK;
4594 }
4595
4596 /*****
4597  * Get Back Buffer
4598  *****/
4599 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4600                                                 IWineD3DSurface **ppBackBuffer) {
4601     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4602     IWineD3DSwapChain *swapChain;
4603     HRESULT hr;
4604
4605     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4606
4607     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4608     if (hr == WINED3D_OK) {
4609         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4610             IWineD3DSwapChain_Release(swapChain);
4611     } else {
4612         *ppBackBuffer = NULL;
4613     }
4614     return hr;
4615 }
4616
4617 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4618     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4619     WARN("(%p) : stub, calling idirect3d for now\n", This);
4620     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4621 }
4622
4623 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4624     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4625     IWineD3DSwapChain *swapChain;
4626     HRESULT hr;
4627
4628     if(iSwapChain > 0) {
4629         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4630         if (hr == WINED3D_OK) {
4631             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4632             IWineD3DSwapChain_Release(swapChain);
4633         } else {
4634             FIXME("(%p) Error getting display mode\n", This);
4635         }
4636     } else {
4637         /* Don't read the real display mode,
4638            but return the stored mode instead. X11 can't change the color
4639            depth, and some apps are pretty angry if they SetDisplayMode from
4640            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4641
4642            Also don't relay to the swapchain because with ddraw it's possible
4643            that there isn't a swapchain at all */
4644         pMode->Width = This->ddraw_width;
4645         pMode->Height = This->ddraw_height;
4646         pMode->Format = This->ddraw_format;
4647         pMode->RefreshRate = 0;
4648         hr = WINED3D_OK;
4649     }
4650
4651     return hr;
4652 }
4653
4654 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4655     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656     TRACE("(%p)->(%p)\n", This, hWnd);
4657
4658     This->ddraw_window = hWnd;
4659     return WINED3D_OK;
4660 }
4661
4662 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4663     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4664     TRACE("(%p)->(%p)\n", This, hWnd);
4665
4666     *hWnd = This->ddraw_window;
4667     return WINED3D_OK;
4668 }
4669
4670 /*****
4671  * Stateblock related functions
4672  *****/
4673
4674 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4675     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4676     IWineD3DStateBlockImpl *object;
4677     HRESULT temp_result;
4678     
4679     TRACE("(%p)\n", This);
4680     
4681     if (This->isRecordingState) {
4682         return WINED3DERR_INVALIDCALL;
4683     }
4684     
4685     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4686     if (NULL == object ) {
4687         FIXME("(%p)Error allocating memory for stateblock\n", This);
4688         return E_OUTOFMEMORY;
4689     }
4690     TRACE("(%p) created object %p\n", This, object);
4691     object->wineD3DDevice= This;
4692     /** FIXME: object->parent       = parent; **/
4693     object->parent       = NULL;
4694     object->blockType    = WINED3DSBT_ALL;
4695     object->ref          = 1;
4696     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4697     
4698     temp_result = allocate_shader_constants(object);
4699     if (WINED3D_OK != temp_result)
4700         return temp_result;
4701
4702     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4703     This->updateStateBlock = object;
4704     This->isRecordingState = TRUE;
4705
4706     TRACE("(%p) recording stateblock %p\n",This , object);
4707     return WINED3D_OK;
4708 }
4709
4710 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4711     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4712
4713     if (!This->isRecordingState) {
4714         FIXME("(%p) not recording! returning error\n", This);
4715         *ppStateBlock = NULL;
4716         return WINED3DERR_INVALIDCALL;
4717     }
4718
4719     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4720     This->isRecordingState = FALSE;
4721     This->updateStateBlock = This->stateBlock;
4722     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4723     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4724     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4725     return WINED3D_OK;
4726 }
4727
4728 /*****
4729  * Scene related functions
4730  *****/
4731 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4732     /* At the moment we have no need for any functionality at the beginning
4733        of a scene                                                          */
4734     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4735     TRACE("(%p) : stub\n", This);
4736     return WINED3D_OK;
4737 }
4738
4739 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4740     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4741     TRACE("(%p)\n", This);
4742     ENTER_GL();
4743     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4744     glFlush();
4745     checkGLcall("glFlush");
4746
4747     TRACE("End Scene\n");
4748     /* If we're using FBOs this isn't needed */
4749     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_targets[0] != NULL) {
4750
4751         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4752         IUnknown *targetContainer = NULL;
4753         if (WINED3D_OK == IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4754             || WINED3D_OK == IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DDevice, (void **)&targetContainer)) {
4755             TRACE("(%p) : Texture rendertarget %p\n", This ,This->render_targets[0]);
4756             /** always dirtify for now. we must find a better way to see that surface have been modified
4757             (Modifications should will only occur via draw-primitive, but we do need better locking
4758             switching to render-to-texture should remove the overhead though.
4759             */
4760             IWineD3DSurface_SetPBufferState(This->render_targets[0], TRUE /* inPBuffer */, FALSE /* inTexture */);
4761             IWineD3DSurface_AddDirtyRect(This->render_targets[0], NULL);
4762             IWineD3DSurface_PreLoad(This->render_targets[0]);
4763             IWineD3DSurface_SetPBufferState(This->render_targets[0], FALSE /* inPBuffer */, FALSE /* inTexture */);
4764             IUnknown_Release(targetContainer);
4765         }
4766     }
4767     This->sceneEnded = TRUE;
4768     LEAVE_GL();
4769     return WINED3D_OK;
4770 }
4771
4772 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4773                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4774                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4775     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4776     IWineD3DSwapChain *swapChain = NULL;
4777     int i;
4778     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4779
4780     TRACE("(%p) Presenting the frame\n", This);
4781
4782     for(i = 0 ; i < swapchains ; i ++) {
4783
4784         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4785         TRACE("presentinng chain %d, %p\n", i, swapChain);
4786         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4787         IWineD3DSwapChain_Release(swapChain);
4788     }
4789
4790     return WINED3D_OK;
4791 }
4792
4793 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4794                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4795     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4796
4797     /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
4798       render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
4799       when the depth-buffer format does not contain stencil buffer information, this method fails. */
4800     GLbitfield     glMask = 0;
4801     GLboolean      old_ztest;
4802     GLfloat        old_z_clear_value;
4803     GLint          old_stencil_clear_value;
4804     GLfloat        old_color_clear_value[4];
4805     unsigned int   i;
4806     CONST WINED3DRECT* curRect;
4807
4808     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
4809           Count, pRects, Flags, Z, Stencil);
4810
4811     ENTER_GL();
4812
4813     glEnable(GL_SCISSOR_TEST);
4814     checkGLcall("glEnable GL_SCISSOR_TEST");
4815
4816     if (Count > 0 && pRects) {
4817         curRect = pRects;
4818     } else {
4819         curRect = NULL;
4820     }
4821
4822     /* Only set the values up once, as they are not changing */
4823     if (Flags & WINED3DCLEAR_STENCIL) {
4824         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4825         glClearStencil(Stencil);
4826         checkGLcall("glClearStencil");
4827         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4828         glStencilMask(0xFFFFFFFF);
4829     }
4830
4831     if (Flags & WINED3DCLEAR_ZBUFFER) {
4832         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4833         glDepthMask(GL_TRUE);
4834         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4835         glClearDepth(Z);
4836         checkGLcall("glClearDepth");
4837         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4838     }
4839
4840     if (Flags & WINED3DCLEAR_TARGET) {
4841         TRACE("Clearing screen with glClear to color %x\n", Color);
4842         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4843         glClearColor(D3DCOLOR_R(Color),
4844                      D3DCOLOR_G(Color),
4845                      D3DCOLOR_B(Color),
4846                      D3DCOLOR_A(Color));
4847         checkGLcall("glClearColor");
4848
4849         /* Clear ALL colors! */
4850         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4851         glMask = glMask | GL_COLOR_BUFFER_BIT;
4852     }
4853
4854     /* Now process each rect in turn */
4855     for (i = 0; i < Count || i == 0; i++) {
4856
4857         if (curRect) {
4858             /* Note gl uses lower left, width/height */
4859             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4860                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4861                   curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4862                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4863             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4864                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4865             checkGLcall("glScissor");
4866         } else {
4867             glScissor(This->stateBlock->viewport.X,
4868                       (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4869                       (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4870                       This->stateBlock->viewport.Width,
4871                       This->stateBlock->viewport.Height);
4872             checkGLcall("glScissor");
4873         }
4874
4875         /* Clear the selected rectangle (or full screen) */
4876         glClear(glMask);
4877         checkGLcall("glClear");
4878
4879         /* Step to the next rectangle */
4880         if (curRect) curRect = curRect + sizeof(WINED3DRECT);
4881     }
4882
4883     /* Restore the old values (why..?) */
4884     if (Flags & WINED3DCLEAR_STENCIL) {
4885         glClearStencil(old_stencil_clear_value);
4886         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4887     }
4888     if (Flags & WINED3DCLEAR_ZBUFFER) {
4889         glDepthMask(old_ztest);
4890         glClearDepth(old_z_clear_value);
4891     }
4892     if (Flags & WINED3DCLEAR_TARGET) {
4893         glClearColor(old_color_clear_value[0],
4894                      old_color_clear_value[1],
4895                      old_color_clear_value[2],
4896                      old_color_clear_value[3]);
4897         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4898                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4899                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4900                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4901     }
4902
4903     glDisable(GL_SCISSOR_TEST);
4904     checkGLcall("glDisable");
4905     LEAVE_GL();
4906
4907     return WINED3D_OK;
4908 }
4909
4910 /*****
4911  * Drawing functions
4912  *****/
4913 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4914                                                 UINT PrimitiveCount) {
4915
4916     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4917     This->stateBlock->streamIsUP = FALSE;
4918
4919     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4920                                debug_d3dprimitivetype(PrimitiveType),
4921                                StartVertex, PrimitiveCount);
4922     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4923                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
4924
4925
4926     return WINED3D_OK;
4927 }
4928
4929 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4930 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4931                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4932                                                            INT baseVIndex, UINT minIndex,
4933                                                            UINT NumVertices, UINT startIndex, UINT primCount) {
4934
4935     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4936     UINT                 idxStride = 2;
4937     IWineD3DIndexBuffer *pIB;
4938     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4939
4940     pIB = This->stateBlock->pIndexData;
4941     This->stateBlock->streamIsUP = FALSE;
4942
4943     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
4944           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4945           minIndex, NumVertices, startIndex, baseVIndex, primCount);
4946
4947     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4948     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4949         idxStride = 2;
4950     } else {
4951         idxStride = 4;
4952     }
4953
4954     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
4955                    idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
4956
4957     return WINED3D_OK;
4958 }
4959
4960 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4961                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4962                                                     UINT VertexStreamZeroStride) {
4963     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4964
4965     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4966              debug_d3dprimitivetype(PrimitiveType),
4967              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4968
4969     /* release the stream source */
4970     if (This->stateBlock->streamSource[0] != NULL) {
4971         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4972     }
4973
4974     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4975     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4976     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4977     This->stateBlock->streamIsUP = TRUE;
4978
4979     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4980                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
4981
4982     /* MSDN specifies stream zero settings must be set to NULL */
4983     This->stateBlock->streamStride[0] = 0;
4984     This->stateBlock->streamSource[0] = NULL;
4985
4986     /*stream zero settings set to null at end, as per the msdn */
4987     return WINED3D_OK;
4988 }
4989
4990 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4991                                                              UINT MinVertexIndex, UINT NumVertices,
4992                                                              UINT PrimitiveCount, CONST void* pIndexData,
4993                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4994                                                              UINT VertexStreamZeroStride) {
4995     int                 idxStride;
4996     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4997
4998     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4999              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5000              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5001              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5002
5003     if (IndexDataFormat == WINED3DFMT_INDEX16) {
5004         idxStride = 2;
5005     } else {
5006         idxStride = 4;
5007     }
5008
5009     /* release the stream and index data */
5010     if (This->stateBlock->streamSource[0] != NULL) {
5011         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
5012     }
5013     if (This->stateBlock->pIndexData) {
5014         IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
5015     }
5016
5017     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5018     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5019     This->stateBlock->streamIsUP = TRUE;
5020     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5021
5022     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
5023
5024     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5025     This->stateBlock->streamSource[0] = NULL;
5026     This->stateBlock->streamStride[0] = 0;
5027     This->stateBlock->pIndexData = NULL;
5028
5029     return WINED3D_OK;
5030 }
5031
5032 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5033
5034     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
5035     return WINED3D_OK;
5036 }
5037  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5038 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
5039     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5040     HRESULT hr = WINED3D_OK;
5041     WINED3DRESOURCETYPE sourceType;
5042     WINED3DRESOURCETYPE destinationType;
5043     int i ,levels;
5044
5045     /* TODO: think about moving the code into IWineD3DBaseTexture  */
5046
5047     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5048
5049     /* verify that the source and destination textures aren't NULL */
5050     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5051         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5052              This, pSourceTexture, pDestinationTexture);
5053         hr = WINED3DERR_INVALIDCALL;
5054     }
5055
5056     if (pSourceTexture == pDestinationTexture) {
5057         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5058              This, pSourceTexture, pDestinationTexture);
5059         hr = WINED3DERR_INVALIDCALL;
5060     }
5061     /* Verify that the source and destination textures are the same type */
5062     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5063     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5064
5065     if (sourceType != destinationType) {
5066         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5067              This);
5068         hr = WINED3DERR_INVALIDCALL;
5069     }
5070
5071     /* check that both textures have the identical numbers of levels  */
5072     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5073         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5074         hr = WINED3DERR_INVALIDCALL;
5075     }
5076
5077     if (WINED3D_OK == hr) {
5078
5079         /* Make sure that the destination texture is loaded */
5080         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5081
5082         /* Update every surface level of the texture */
5083         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5084
5085         switch (sourceType) {
5086         case WINED3DRTYPE_TEXTURE:
5087             {
5088                 IWineD3DSurface *srcSurface;
5089                 IWineD3DSurface *destSurface;
5090
5091                 for (i = 0 ; i < levels ; ++i) {
5092                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
5093                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5094                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5095                     IWineD3DSurface_Release(srcSurface);
5096                     IWineD3DSurface_Release(destSurface);
5097                     if (WINED3D_OK != hr) {
5098                         WARN("(%p) : Call to update surface failed\n", This);
5099                         return hr;
5100                     }
5101                 }
5102             }
5103             break;
5104         case WINED3DRTYPE_CUBETEXTURE:
5105             {
5106                 IWineD3DSurface *srcSurface;
5107                 IWineD3DSurface *destSurface;
5108                 WINED3DCUBEMAP_FACES faceType;
5109
5110                 for (i = 0 ; i < levels ; ++i) {
5111                     /* Update each cube face */
5112                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5113                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
5114                         if (WINED3D_OK != hr) {
5115                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5116                         } else {
5117                             TRACE("Got srcSurface %p\n", srcSurface);
5118                         }
5119                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5120                         if (WINED3D_OK != hr) {
5121                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5122                         } else {
5123                             TRACE("Got desrSurface %p\n", destSurface);
5124                         }
5125                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5126                         IWineD3DSurface_Release(srcSurface);
5127                         IWineD3DSurface_Release(destSurface);
5128                         if (WINED3D_OK != hr) {
5129                             WARN("(%p) : Call to update surface failed\n", This);
5130                             return hr;
5131                         }
5132                     }
5133                 }
5134             }
5135             break;
5136 #if 0 /* TODO: Add support for volume textures */
5137         case WINED3DRTYPE_VOLUMETEXTURE:
5138             {
5139                 IWineD3DVolume  srcVolume  = NULL;
5140                 IWineD3DSurface destVolume = NULL;
5141
5142                 for (i = 0 ; i < levels ; ++i) {
5143                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5144                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5145                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
5146                     IWineD3DVolume_Release(srcSurface);
5147                     IWineD3DVolume_Release(destSurface);
5148                     if (WINED3D_OK != hr) {
5149                         WARN("(%p) : Call to update volume failed\n", This);
5150                         return hr;
5151                     }
5152                 }
5153             }
5154             break;
5155 #endif
5156         default:
5157             FIXME("(%p) : Unsupported source and destination type\n", This);
5158             hr = WINED3DERR_INVALIDCALL;
5159         }
5160     }
5161
5162     return hr;
5163 }
5164
5165 static HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
5166                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
5167                                                 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
5168     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5169
5170     TRACE("(%p) : stub\n", This);
5171     return WINED3D_OK;
5172 }
5173 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
5174     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5175     /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5176     *  NOTE It may be best to move the code into surface to occomplish this
5177     ****************************************/
5178
5179     WINED3DSURFACE_DESC surfaceDesc;
5180     unsigned int surfaceWidth, surfaceHeight;
5181     glDescriptor *targetGlDescription  = NULL;
5182     glDescriptor *surfaceGlDescription = NULL;
5183     IWineD3DSwapChainImpl *container = NULL;
5184     
5185     IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
5186     IWineD3DSurface_GetGlDesc(pSurface,      &surfaceGlDescription);
5187     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5188
5189     surfaceDesc.Width  = &surfaceWidth;
5190     surfaceDesc.Height = &surfaceHeight;
5191     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5192    /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5193
5194     /* Ok, I may need to setup some kind of active swapchain reference on the device */
5195     IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
5196     ENTER_GL();
5197     /* TODO: opengl Context switching for swapchains etc... */
5198     if (NULL != container  || pRenderTarget == This->render_targets[0] || pRenderTarget == This->depthStencilBuffer) {
5199         if (NULL != container  && (pRenderTarget == container->backBuffer[0])) {
5200             glReadBuffer(GL_BACK);
5201             vcheckGLcall("glReadBuffer(GL_BACK)");
5202         } else if ((NULL != container  && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->render_targets[0])) {
5203             glReadBuffer(GL_FRONT);
5204             vcheckGLcall("glReadBuffer(GL_FRONT)");
5205         } else if (pRenderTarget == This->depthStencilBuffer) {
5206             FIXME("Reading of depthstencil not yet supported\n");
5207         }
5208
5209         glReadPixels(0,
5210                     0,
5211                     surfaceWidth,
5212                     surfaceHeight,
5213                     surfaceGlDescription->glFormat,
5214                     surfaceGlDescription->glType,
5215                     (void *)IWineD3DSurface_GetData(pSurface));
5216         vcheckGLcall("glReadPixels(...)");
5217         if(NULL != container ){
5218             IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
5219         }
5220     } else {
5221         IWineD3DBaseTexture *container;
5222         GLenum textureDimensions = GL_TEXTURE_2D;
5223
5224         if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
5225             textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
5226             IWineD3DBaseTexture_Release(container);
5227         }
5228         /* TODO: 2D -> Cube surface coppies etc.. */
5229         if (surfaceGlDescription->target != textureDimensions) {
5230             FIXME("(%p) : Texture dimension mismatch\n", This);
5231         }
5232         glEnable(textureDimensions);
5233         vcheckGLcall("glEnable(GL_TEXTURE_...)");
5234         /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5235         glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
5236         vcheckGLcall("glBindTexture");
5237         glGetTexImage(surfaceGlDescription->target,
5238                         surfaceGlDescription->level,
5239                         surfaceGlDescription->glFormat,
5240                         surfaceGlDescription->glType,
5241                         (void *)IWineD3DSurface_GetData(pSurface));
5242         glDisable(textureDimensions);
5243         vcheckGLcall("glDisable(GL_TEXTURE_...)");
5244
5245     }
5246     LEAVE_GL();
5247     return WINED3D_OK;
5248 }
5249
5250 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5251     IWineD3DSwapChain *swapChain;
5252     HRESULT hr;
5253     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5254     if(hr == WINED3D_OK) {
5255         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5256                 IWineD3DSwapChain_Release(swapChain);
5257     }
5258     return hr;
5259 }
5260
5261 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5262     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5263     /* return a sensible default */
5264     *pNumPasses = 1;
5265     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5266     FIXME("(%p) : stub\n", This);
5267     return WINED3D_OK;
5268 }
5269
5270 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5271     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5272     int j;
5273     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5274     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5275         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5276         return WINED3DERR_INVALIDCALL;
5277     }
5278     for (j = 0; j < 256; ++j) {
5279         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5280         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5281         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5282         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5283     }
5284     TRACE("(%p) : returning\n", This);
5285     return WINED3D_OK;
5286 }
5287
5288 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5289     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5290     int j;
5291     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5292     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5293         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5294         return WINED3DERR_INVALIDCALL;
5295     }
5296     for (j = 0; j < 256; ++j) {
5297         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5298         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5299         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5300         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5301     }
5302     TRACE("(%p) : returning\n", This);
5303     return WINED3D_OK;
5304 }
5305
5306 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5307     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5308     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5309     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5310         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5311         return WINED3DERR_INVALIDCALL;
5312     }
5313     /*TODO: stateblocks */
5314     This->currentPalette = PaletteNumber;
5315     TRACE("(%p) : returning\n", This);
5316     return WINED3D_OK;
5317 }
5318
5319 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5320     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5321     if (PaletteNumber == NULL) {
5322         WARN("(%p) : returning Invalid Call\n", This);
5323         return WINED3DERR_INVALIDCALL;
5324     }
5325     /*TODO: stateblocks */
5326     *PaletteNumber = This->currentPalette;
5327     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5328     return WINED3D_OK;
5329 }
5330
5331 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5332     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5333     static BOOL showFixmes = TRUE;
5334     if (showFixmes) {
5335         FIXME("(%p) : stub\n", This);
5336         showFixmes = FALSE;
5337     }
5338
5339     This->softwareVertexProcessing = bSoftware;
5340     return WINED3D_OK;
5341 }
5342
5343
5344 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5345     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5346     static BOOL showFixmes = TRUE;
5347     if (showFixmes) {
5348         FIXME("(%p) : stub\n", This);
5349         showFixmes = FALSE;
5350     }
5351     return This->softwareVertexProcessing;
5352 }
5353
5354
5355 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5356     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5357     IWineD3DSwapChain *swapChain;
5358     HRESULT hr;
5359
5360     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5361
5362     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5363     if(hr == WINED3D_OK){
5364         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5365         IWineD3DSwapChain_Release(swapChain);
5366     }else{
5367         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5368     }
5369     return hr;
5370 }
5371
5372
5373 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5374     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5375     static BOOL showfixmes = TRUE;
5376     if(nSegments != 0.0f) {
5377         if( showfixmes) {
5378             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5379             showfixmes = FALSE;
5380         }
5381     }
5382     return WINED3D_OK;
5383 }
5384
5385 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5386     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5387     static BOOL showfixmes = TRUE;
5388     if( showfixmes) {
5389         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5390         showfixmes = FALSE;
5391     }
5392     return 0.0f;
5393 }
5394
5395 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5396     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5397     /** TODO: remove casts to IWineD3DSurfaceImpl
5398      *       NOTE: move code to surface to accomplish this
5399       ****************************************/
5400     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5401     int srcWidth, srcHeight;
5402     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5403     WINED3DFORMAT destFormat, srcFormat;
5404     UINT          destSize;
5405     int destLeft, destTop;
5406     WINED3DPOOL       srcPool, destPool;
5407     int offset    = 0;
5408     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5409     glDescriptor *glDescription = NULL;
5410     GLenum textureDimensions = GL_TEXTURE_2D;
5411     IWineD3DBaseTexture *baseTexture;
5412
5413     WINED3DSURFACE_DESC  winedesc;
5414
5415     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5416     memset(&winedesc, 0, sizeof(winedesc));
5417     winedesc.Width  = &srcSurfaceWidth;
5418     winedesc.Height = &srcSurfaceHeight;
5419     winedesc.Pool   = &srcPool;
5420     winedesc.Format = &srcFormat;
5421
5422     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5423
5424     winedesc.Width  = &destSurfaceWidth;
5425     winedesc.Height = &destSurfaceHeight;
5426     winedesc.Pool   = &destPool;
5427     winedesc.Format = &destFormat;
5428     winedesc.Size   = &destSize;
5429
5430     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5431
5432     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5433         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5434         return WINED3DERR_INVALIDCALL;
5435     }
5436
5437     if (destFormat == WINED3DFMT_UNKNOWN) {
5438         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5439         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5440
5441         /* Get the update surface description */
5442         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5443     }
5444
5445     /* Make sure the surface is loaded and up to date */
5446     IWineD3DSurface_PreLoad(pDestinationSurface);
5447
5448     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5449
5450     ENTER_GL();
5451
5452     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5453     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5454     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
5455     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5456     destTop    = pDestPoint  ? pDestPoint->y : 0;
5457
5458
5459     /* This function doesn't support compressed textures
5460     the pitch is just bytesPerPixel * width */
5461     if(srcWidth != srcSurfaceWidth  || (pSourceRect != NULL && pSourceRect->left != 0) ){
5462         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5463         offset   += pSourceRect->left * pSrcSurface->bytesPerPixel;
5464         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5465     }
5466     /* TODO DXT formats */
5467
5468     if(pSourceRect != NULL && pSourceRect->top != 0){
5469        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5470     }
5471     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5472     ,This
5473     ,glDescription->level
5474     ,destLeft
5475     ,destTop
5476     ,srcWidth
5477     ,srcHeight
5478     ,glDescription->glFormat
5479     ,glDescription->glType
5480     ,IWineD3DSurface_GetData(pSourceSurface)
5481     );
5482
5483     /* Sanity check */
5484     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5485
5486         /* need to lock the surface to get the data */
5487         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5488     }
5489
5490     /* TODO: Cube and volume support */
5491     if(rowoffset != 0){
5492         /* not a whole row so we have to do it a line at a time */
5493         int j;
5494
5495         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5496         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5497
5498         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5499
5500                 glTexSubImage2D(glDescription->target
5501                     ,glDescription->level
5502                     ,destLeft
5503                     ,j
5504                     ,srcWidth
5505                     ,1
5506                     ,glDescription->glFormat
5507                     ,glDescription->glType
5508                     ,data /* could be quicker using */
5509                 );
5510             data += rowoffset;
5511         }
5512
5513     } else { /* Full width, so just write out the whole texture */
5514
5515         if (WINED3DFMT_DXT1 == destFormat ||
5516             WINED3DFMT_DXT2 == destFormat ||
5517             WINED3DFMT_DXT3 == destFormat ||
5518             WINED3DFMT_DXT4 == destFormat ||
5519             WINED3DFMT_DXT5 == destFormat) {
5520             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5521                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5522                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5523                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5524                 } if (destFormat != srcFormat) {
5525                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5526                 } else {
5527                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5528                                                         glDescription->level,
5529                                                         glDescription->glFormatInternal,
5530                                                         srcWidth,
5531                                                         srcHeight,
5532                                                         0,
5533                                                         destSize,
5534                                                         IWineD3DSurface_GetData(pSourceSurface));
5535                 }
5536             } else {
5537                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5538             }
5539
5540
5541         } else {
5542             if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5543
5544                 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5545                 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5546                 data returned by GetData non-power2 width/height with hardware non-power2
5547                 pow2Width/height are set to surface width height, repacking isn't needed so it
5548                 doesn't matter which function gets called. */
5549                 glTexSubImage2D(glDescription->target
5550                         ,glDescription->level
5551                         ,destLeft
5552                         ,destTop
5553                         ,srcWidth
5554                         ,srcHeight
5555                         ,glDescription->glFormat
5556                         ,glDescription->glType
5557                         ,IWineD3DSurface_GetData(pSourceSurface)
5558                     );
5559             } else {
5560
5561                 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5562                 glTexSubImage2D(glDescription->target
5563                     ,glDescription->level
5564                     ,destLeft
5565                     ,destTop
5566                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5567                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5568                     ,glDescription->glFormat
5569                     ,glDescription->glType
5570                     ,IWineD3DSurface_GetData(pSourceSurface)
5571                 );
5572             }
5573
5574         }
5575      }
5576     checkGLcall("glTexSubImage2D");
5577     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
5578
5579     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5580      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5581      * surface bigger than it needs to be hmm.. */
5582     if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5583         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5584         IWineD3DBaseTexture_Release(baseTexture);
5585     }
5586
5587     glDisable(textureDimensions); /* This needs to be managed better.... */
5588     LEAVE_GL();
5589
5590     return WINED3D_OK;
5591 }
5592
5593 /* Implementation details at http://developer.nvidia.com/attach/6494
5594 and
5595 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5596 hmm.. no longer supported use
5597 OpenGL evaluators or  tessellate surfaces within your application.
5598 */
5599
5600 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5601 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5602     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5603     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5604     FIXME("(%p) : Stub\n", This);
5605     return WINED3D_OK;
5606
5607 }
5608
5609 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5610 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5611     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5612     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5613     FIXME("(%p) : Stub\n", This);
5614     return WINED3D_OK;
5615 }
5616
5617 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5618     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5619     TRACE("(%p) Handle(%d)\n", This, Handle);
5620     FIXME("(%p) : Stub\n", This);
5621     return WINED3D_OK;
5622 }
5623
5624 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
5625     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5626     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
5627     DDBLTFX BltFx;
5628     TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
5629
5630     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
5631         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5632         return WINED3DERR_INVALIDCALL;
5633     }
5634
5635     /* Just forward this to the DirectDraw blitting engine */
5636     memset(&BltFx, 0, sizeof(BltFx));
5637     BltFx.dwSize = sizeof(BltFx);
5638     BltFx.u5.dwFillColor = color;
5639     return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
5640 }
5641
5642 /* rendertarget and deptth stencil functions */
5643 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5644     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5645
5646     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5647         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5648         return WINED3DERR_INVALIDCALL;
5649     }
5650
5651     *ppRenderTarget = This->render_targets[RenderTargetIndex];
5652     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5653     /* Note inc ref on returned surface */
5654     if(*ppRenderTarget != NULL)
5655         IWineD3DSurface_AddRef(*ppRenderTarget);
5656     return WINED3D_OK;
5657 }
5658
5659 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
5660     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5661     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
5662     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
5663     IWineD3DSwapChainImpl *Swapchain;
5664     HRESULT hr;
5665
5666     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
5667
5668     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
5669     if(hr != WINED3D_OK) {
5670         ERR("Can't get the swapchain\n");
5671         return hr;
5672     }
5673
5674     /* Make sure to release the swapchain */
5675     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
5676
5677     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
5678         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5679         return WINED3DERR_INVALIDCALL;
5680     }
5681     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
5682         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5683         return WINED3DERR_INVALIDCALL;
5684     }
5685
5686     if(Swapchain->frontBuffer != Front) {
5687         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
5688
5689         if(Swapchain->frontBuffer)
5690             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
5691         Swapchain->frontBuffer = Front;
5692
5693         if(Swapchain->frontBuffer) {
5694             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
5695         }
5696     }
5697
5698     if(Back && !Swapchain->backBuffer) {
5699         /* We need memory for the back buffer array - only one back buffer this way */
5700         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
5701         if(!Swapchain->backBuffer) {
5702             ERR("Out of memory\n");
5703             return E_OUTOFMEMORY;
5704         }
5705     }
5706
5707     if(Swapchain->backBuffer[0] != Back) {
5708         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
5709         ENTER_GL();
5710         if(!Swapchain->backBuffer[0]) {
5711             /* GL was told to draw to the front buffer at creation,
5712              * undo that
5713              */
5714             glDrawBuffer(GL_BACK);
5715             checkGLcall("glDrawBuffer(GL_BACK)");
5716             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
5717             Swapchain->presentParms.BackBufferCount = 1;
5718         } else if (!Back) {
5719             /* That makes problems - disable for now */
5720             /* glDrawBuffer(GL_FRONT); */
5721             checkGLcall("glDrawBuffer(GL_FRONT)");
5722             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
5723             Swapchain->presentParms.BackBufferCount = 0;
5724         }
5725         LEAVE_GL();
5726
5727         if(Swapchain->backBuffer[0])
5728             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
5729         Swapchain->backBuffer[0] = Back;
5730
5731         if(Swapchain->backBuffer[0]) {
5732             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5733         } else {
5734             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5735         }
5736
5737     }
5738
5739     return WINED3D_OK;
5740 }
5741
5742 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5743     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5744     *ppZStencilSurface = This->depthStencilBuffer;
5745     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5746
5747     if(*ppZStencilSurface != NULL) {
5748         /* Note inc ref on returned surface */
5749         IWineD3DSurface_AddRef(*ppZStencilSurface);
5750     }
5751     return WINED3D_OK;
5752 }
5753
5754 static void bind_fbo(IWineD3DDevice *iface) {
5755     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5756
5757     if (!This->fbo) {
5758         GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
5759         checkGLcall("glGenFramebuffersEXT()");
5760     }
5761     GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
5762     checkGLcall("glBindFramebuffer()");
5763 }
5764
5765 /* TODO: Handle stencil attachments */
5766 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5767     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5768     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5769
5770     This->depth_copy_state = WINED3D_DCS_NO_COPY;
5771
5772     bind_fbo(iface);
5773
5774     if (depth_stencil_impl) {
5775         GLenum texttarget, target;
5776
5777         IWineD3DSurface_PreLoad(depth_stencil);
5778         texttarget = depth_stencil_impl->glDescription.target;
5779         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5780
5781         glBindTexture(target, depth_stencil_impl->glDescription.textureName);
5782         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5783         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5784         glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5785         glBindTexture(target, 0);
5786
5787         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5788         checkGLcall("glFramebufferTexture2DEXT()");
5789     } else {
5790         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5791         checkGLcall("glFramebufferTexture2DEXT()");
5792     }
5793
5794     if (!This->render_offscreen) {
5795         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5796         checkGLcall("glBindFramebuffer()");
5797     }
5798 }
5799
5800 static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5801     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5802     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5803
5804     if (idx >= GL_LIMITS(buffers)) {
5805         ERR("%p : Trying to set render target %d, but only %d supported\n", This, idx, GL_LIMITS(buffers));
5806     }
5807
5808     bind_fbo(iface);
5809
5810     if (rtimpl) {
5811         GLenum texttarget, target;
5812
5813         IWineD3DSurface_PreLoad(render_target);
5814         texttarget = rtimpl->glDescription.target;
5815         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5816
5817         glBindTexture(target, rtimpl->glDescription.textureName);
5818         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5819         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5820         glBindTexture(target, 0);
5821
5822         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, rtimpl->glDescription.textureName, 0));
5823         checkGLcall("glFramebufferTexture2DEXT()");
5824
5825         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5826     } else {
5827         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5828         checkGLcall("glFramebufferTexture2DEXT()");
5829
5830         This->draw_buffers[idx] = GL_NONE;
5831     }
5832
5833     if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5834         GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5835         checkGLcall("glDrawBuffers()");
5836     }
5837
5838     if (!This->render_offscreen) {
5839         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5840         checkGLcall("glBindFramebuffer()");
5841     }
5842 }
5843
5844 /* internal static helper functions */
5845 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5846                                                 IWineD3DSurface *RenderSurface);
5847
5848 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5849     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5850     HRESULT  hr = WINED3D_OK;
5851     WINED3DVIEWPORT viewport;
5852
5853     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5854
5855     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5856         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5857         return WINED3DERR_INVALIDCALL;
5858     }
5859
5860     /* MSDN says that null disables the render target
5861     but a device must always be associated with a render target
5862     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5863
5864     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5865     for more details
5866     */
5867     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5868         FIXME("Trying to set render target 0 to NULL\n");
5869         return WINED3DERR_INVALIDCALL;
5870     }
5871     /* TODO: replace Impl* usage with interface usage */
5872     if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5873         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);
5874         return WINED3DERR_INVALIDCALL;
5875     }
5876     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5877      *        builds, but I think wine counts as a 'debug' build for now.
5878       ******************************/
5879     /* If we are trying to set what we already have, don't bother */
5880     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5881         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5882     } else {
5883         /* Otherwise, set the render target up */
5884
5885         if (!This->sceneEnded) {
5886             IWineD3DDevice_EndScene(iface);
5887         }
5888         TRACE("clearing renderer\n");
5889         /* IWineD3DDeviceImpl_CleanRender(iface); */
5890         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5891         depending on the renter target implementation being used.
5892         A shared context implementation will share all buffers between all rendertargets (including swapchains),
5893         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5894         stencil buffer and incure an extra memory overhead */
5895         if (RenderTargetIndex == 0) {
5896             hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5897         } else {
5898             hr = WINED3D_OK;
5899         }
5900
5901         /* Replace the render target */
5902         if (This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5903         This->render_targets[RenderTargetIndex] = pRenderTarget;
5904         if (pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5905
5906         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5907             set_render_target_fbo(iface, RenderTargetIndex, pRenderTarget);
5908         }
5909     }
5910
5911     if (SUCCEEDED(hr)) {
5912         /* Finally, reset the viewport as the MSDN states. */
5913         /* TODO: Replace impl usage */
5914         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5915         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5916         viewport.X      = 0;
5917         viewport.Y      = 0;
5918         viewport.MaxZ   = 1.0f;
5919         viewport.MinZ   = 0.0f;
5920         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5921     } else {
5922         FIXME("Unknown error setting the render target\n");
5923     }
5924     This->sceneEnded = FALSE;
5925     return hr;
5926 }
5927
5928 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5929     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5930     HRESULT  hr = WINED3D_OK;
5931     IWineD3DSurface *tmp;
5932
5933     TRACE("(%p) Swapping z-buffer\n",This);
5934
5935     if (pNewZStencil == This->stencilBufferTarget) {
5936         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5937     } else {
5938         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5939         * depending on the renter target implementation being used.
5940         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5941         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5942         * stencil buffer and incure an extra memory overhead
5943          ******************************************************/
5944
5945
5946         tmp = This->stencilBufferTarget;
5947         This->stencilBufferTarget = pNewZStencil;
5948         /* should we be calling the parent or the wined3d surface? */
5949         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5950         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5951         hr = WINED3D_OK;
5952         /** TODO: glEnable/glDisable on depth/stencil    depending on
5953          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
5954           **********************************************************/
5955         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5956             set_depth_stencil_fbo(iface, pNewZStencil);
5957         }
5958     }
5959
5960     return hr;
5961 }
5962
5963
5964 #ifdef GL_VERSION_1_3
5965 /* Internal functions not in DirectX */
5966  /** TODO: move this off to the opengl context manager
5967  *(the swapchain doesn't need to know anything about offscreen rendering!)
5968   ****************************************************/
5969
5970 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5971 {
5972     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5973
5974     TRACE("(%p), %p\n", This, swapchain);
5975
5976     if (swapchain->win != swapchain->drawable) {
5977         /* Set everything back the way it ws */
5978         swapchain->render_ctx = swapchain->glCtx;
5979         swapchain->drawable   = swapchain->win;
5980     }
5981     return WINED3D_OK;
5982 }
5983
5984 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5985 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5986     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5987     int i;
5988     unsigned int width;
5989     unsigned int height;
5990     WINED3DFORMAT format;
5991     WINED3DSURFACE_DESC surfaceDesc;
5992     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5993     surfaceDesc.Width  = &width;
5994     surfaceDesc.Height = &height;
5995     surfaceDesc.Format = &format;
5996     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5997     *context = NULL;
5998     /* I need a get width/height function (and should do something with the format) */
5999     for (i = 0; i < CONTEXT_CACHE; ++i) {
6000         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6001         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6002         the pSurface can be set to 0 allowing it to be reused from cache **/
6003         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
6004           && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
6005             *context = &This->contextCache[i];
6006             break;
6007         }
6008         if (This->contextCache[i].Width == 0) {
6009             This->contextCache[i].pSurface = pSurface;
6010             This->contextCache[i].Width    = width;
6011             This->contextCache[i].Height   = height;
6012             *context = &This->contextCache[i];
6013             break;
6014         }
6015     }
6016     if (i == CONTEXT_CACHE) {
6017         int minUsage = 0x7FFFFFFF; /* MAX_INT */
6018         glContext *dropContext = 0;
6019         for (i = 0; i < CONTEXT_CACHE; i++) {
6020             if (This->contextCache[i].usedcount < minUsage) {
6021                 dropContext = &This->contextCache[i];
6022                 minUsage = This->contextCache[i].usedcount;
6023             }
6024         }
6025         /* clean up the context (this doesn't work for ATI at the moment */
6026 #if 0
6027         glXDestroyContext(swapchain->display, dropContext->context);
6028         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
6029 #endif
6030         FIXME("Leak\n");
6031         dropContext->Width = 0;
6032         dropContext->pSurface = pSurface;
6033         *context = dropContext;
6034     } else {
6035         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6036           for (i = 0; i < CONTEXT_CACHE; i++) {
6037              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
6038           }
6039         }
6040     }
6041     if (*context != NULL)
6042         return WINED3D_OK;
6043     else
6044         return E_OUTOFMEMORY;
6045 }
6046 #endif
6047
6048 /* Reapply the device stateblock */
6049 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
6050
6051     BOOL oldRecording;  
6052     IWineD3DStateBlockImpl *oldUpdateStateBlock;
6053     DWORD i;
6054
6055     /* Disable recording */
6056     oldUpdateStateBlock = This->updateStateBlock;
6057     oldRecording= This->isRecordingState;
6058     This->isRecordingState = FALSE;
6059     This->updateStateBlock = This->stateBlock;
6060
6061     /* Reapply the state block */ 
6062     IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
6063
6064     /* Temporaryily mark all render states dirty to force reapplication
6065      * until the context management for is integrated with the state management
6066      */
6067     for(i = 1; i < WINEHIGHEST_RENDER_STATE; i++) {
6068         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(i));
6069     }
6070
6071     /* Restore recording */
6072     This->isRecordingState = oldRecording;
6073     This->updateStateBlock = oldUpdateStateBlock;
6074 }
6075
6076 /* Set offscreen rendering. When rendering offscreen the surface will be
6077  * rendered upside down to compensate for the fact that D3D texture coordinates
6078  * are flipped compared to GL texture coordinates. The cullmode is affected by
6079  * this, so it must be updated. To update the cullmode stateblock recording has
6080  * to be temporarily disabled. The new state management code will hopefully
6081  * make this unnecessary */
6082 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
6083
6084     BOOL oldRecording;
6085     IWineD3DStateBlockImpl *oldUpdateStateBlock;
6086
6087     /* Nothing to update, return. */
6088     if (This->render_offscreen == isTexture) return;
6089
6090     /* Disable recording */
6091     oldUpdateStateBlock = This->updateStateBlock;
6092     oldRecording= This->isRecordingState;
6093     This->isRecordingState = FALSE;
6094     This->updateStateBlock = This->stateBlock;
6095
6096     This->render_offscreen = isTexture;
6097     if (This->depth_copy_state != WINED3D_DCS_NO_COPY) {
6098         This->depth_copy_state = WINED3D_DCS_COPY;
6099     }
6100     This->last_was_rhw = FALSE;
6101     This->proj_valid = FALSE;
6102     IWineD3DDeviceImpl_MarkStateDirty(This, WINED3DRS_CULLMODE);
6103
6104     /* Restore recording */
6105     This->isRecordingState = oldRecording;
6106     This->updateStateBlock = oldUpdateStateBlock;
6107 }
6108
6109 /* Returns an array of compatible FBconfig(s).
6110  * The array must be freed with XFree. Requires ENTER_GL() */
6111
6112 static GLXFBConfig* device_find_fbconfigs(
6113     IWineD3DDeviceImpl* This,
6114     IWineD3DSwapChainImpl* implicitSwapchainImpl,
6115     IWineD3DSurface* RenderSurface) {
6116
6117     GLXFBConfig* cfgs = NULL;
6118     int nCfgs = 0;
6119     int attribs[256];
6120     int nAttribs = 0;
6121
6122     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
6123     WINED3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
6124     WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
6125
6126     /**TODO:
6127         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off, 
6128         it StencilSurface != NULL && zBufferTarget == NULL switch it on
6129     */
6130
6131 #define PUSH1(att)        attribs[nAttribs++] = (att);
6132 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6133
6134     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6135
6136     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
6137     PUSH2(GLX_X_RENDERABLE,  TRUE);
6138     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
6139     TRACE("calling makeglcfg\n");
6140     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
6141     PUSH1(None);
6142     TRACE("calling chooseFGConfig\n");
6143     cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
6144                              DefaultScreen(implicitSwapchainImpl->display),
6145                              attribs, &nCfgs);
6146     if (cfgs == NULL) {
6147         /* OK we didn't find the exact config, so use any reasonable match */
6148         /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
6149            why we failed. */
6150         static BOOL show_message = TRUE;
6151         if (show_message) {
6152             ERR("Failed to find exact match, finding alternative but you may "
6153                 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
6154             show_message = FALSE;
6155         }
6156         nAttribs = 0;
6157         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
6158         /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
6159         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
6160         PUSH2(GLX_DOUBLEBUFFER, FALSE);
6161         TRACE("calling makeglcfg\n");
6162         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
6163         PUSH1(None);
6164         cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
6165                                  DefaultScreen(implicitSwapchainImpl->display),
6166                                  attribs, &nCfgs);
6167     }
6168                                                                                                                                                                       
6169     if (cfgs == NULL) {
6170         ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
6171             BackBufferFormat, debug_d3dformat(BackBufferFormat),
6172             StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
6173     } else {
6174 #ifdef EXTRA_TRACES
6175         int i;
6176         for (i = 0; i < nCfgs; ++i) {
6177             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
6178             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
6179             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
6180         }
6181         if (NULL != This->renderTarget) {
6182             glFlush();
6183             vcheckGLcall("glFlush");
6184             /** This is only useful if the old render target was a swapchain,
6185             * we need to supercede this with a function that displays
6186             * the current buffer on the screen. This is easy to do in glx1.3 but
6187             * we need to do copy-write pixels in glx 1.2.
6188             ************************************************/
6189             glXSwapBuffers(implicitSwapChainImpl->display,
6190                            implicitSwapChainImpl->drawable);
6191             printf("Hit Enter to get next frame ...\n");
6192             getchar();
6193         }
6194 #endif
6195     }
6196 #undef PUSH1
6197 #undef PUSH2
6198
6199    return cfgs;
6200 }
6201
6202 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6203 * the functionality needs splitting up so that we don't do more than we should do.
6204 * this only seems to impact performance a little.
6205  ******************************/
6206 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
6207                                                IWineD3DSurface *RenderSurface) {
6208
6209     /**
6210     * Currently only active for GLX >= 1.3
6211     * for others versions we'll have to use GLXPixmaps
6212     *
6213     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6214     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6215     * so only check OpenGL version
6216     * ..........................
6217     * I don't believe that it is a problem with NVidia headers,
6218     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6219     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6220     * ATI Note:
6221     * Your application will report GLX version 1.2 on glXQueryVersion.
6222     * However, it is safe to call the GLX 1.3 functions as described below.
6223     */
6224 #if defined(GL_VERSION_1_3)
6225
6226     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6227     GLXFBConfig* cfgs = NULL;
6228     IWineD3DSwapChain     *currentSwapchain;
6229     IWineD3DSwapChainImpl *currentSwapchainImpl;
6230     IWineD3DSwapChain     *implicitSwapchain;
6231     IWineD3DSwapChainImpl *implicitSwapchainImpl;
6232     IWineD3DSwapChain     *renderSurfaceSwapchain;
6233     IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
6234
6235     /* Obtain a reference to the device implicit swapchain,
6236      * the swapchain of the current render target,
6237      * and the swapchain of the new render target.
6238      * Fallback to device implicit swapchain if the current render target doesn't have one */
6239     IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
6240     IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
6241     IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DSwapChain, (void **)&currentSwapchain);
6242     if (currentSwapchain == NULL)
6243         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
6244
6245     currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
6246     implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
6247     renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
6248
6249     ENTER_GL();
6250
6251     /**
6252     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6253     *  renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
6254      **********************************************************************/
6255     if (renderSurfaceSwapchain != NULL) {
6256
6257         /* We also need to make sure that the lights &co are also in the context of the swapchains */
6258         /* FIXME: If the render target gets sent to the frontBuffer, should we be presenting it raw? */
6259         TRACE("making swapchain active\n");
6260         if (RenderSurface != This->render_targets[0]) {
6261             BOOL backbuf = FALSE;
6262             int i;
6263
6264             for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
6265                 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
6266                     backbuf = TRUE;
6267                     break;
6268                 }
6269             }
6270
6271             if (backbuf) {
6272             } else {
6273                 /* This could be flagged so that some operations work directly with the front buffer */
6274                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
6275             }
6276             if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
6277                                renderSurfaceSwapchainImpl->win,
6278                                renderSurfaceSwapchainImpl->glCtx) == False) {
6279
6280                 TRACE("Error in setting current context: context %p drawable %ld !\n",
6281                        implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
6282             }
6283             checkGLcall("glXMakeContextCurrent");
6284
6285             /* Clean up the old context */
6286             IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
6287
6288             /* Reapply the stateblock, and set the device not to render to texture */
6289             device_reapply_stateblock(This);
6290             device_render_to_texture(This, FALSE);
6291         }
6292
6293     /* Offscreen rendering: PBuffers (currently disabled).
6294      * Also note that this path is never reached if FBOs are supported */
6295     } else if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER &&
6296                (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
6297
6298         /** ********************************************************************
6299         * This is a quickly hacked out implementation of offscreen textures.
6300         * It will work in most cases but there may be problems if the client
6301         * modifies the texture directly, or expects the contents of the rendertarget
6302         * to be persistent.
6303         *
6304         * There are some real speed vs compatibility issues here:
6305         *    we should really use a new context for every texture, but that eats ram.
6306         *    we should also be restoring the texture to the pbuffer but that eats CPU
6307         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6308         *    but if this means reusing the display backbuffer then we need to make sure that
6309         *    states are correctly preserved.
6310         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6311         * and gain a good performance increase at the cost of compatibility.
6312         * I would suggest that, when this is the case, a user configurable flag be made
6313         * available, allowing the user to choose the best emulated experience for them.
6314          *********************************************************************/
6315
6316         XVisualInfo *visinfo;
6317         glContext   *newContext;
6318
6319         /* Here were using a shared context model */
6320         if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6321             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6322         }
6323
6324         /* If the context doesn't exist then create a new one */
6325         /* TODO: This should really be part of findGlContext */
6326         if (NULL == newContext->context) {
6327
6328             int attribs[256];
6329             int nAttribs = 0;
6330
6331             TRACE("making new buffer\n");
6332             attribs[nAttribs++] = GLX_PBUFFER_WIDTH; 
6333             attribs[nAttribs++] = newContext->Width;
6334             attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
6335             attribs[nAttribs++] = newContext->Height;
6336             attribs[nAttribs++] = None;
6337
6338             newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
6339
6340             /** ****************************************
6341             *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6342             *they note:
6343             *   In future releases, we may provide the calls glXCreateNewContext,
6344             *   glXQueryDrawable and glXMakeContextCurrent.
6345             *    so until then we have to use glXGetVisualFromFBConfig &co..
6346             ********************************************/
6347
6348             visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
6349             if (!visinfo) {
6350                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6351             } else {
6352                 newContext->context = glXCreateContext(
6353                     implicitSwapchainImpl->display, visinfo,
6354                     implicitSwapchainImpl->glCtx, GL_TRUE);
6355
6356                 XFree(visinfo);
6357             }
6358         }
6359         if (NULL == newContext || NULL == newContext->context) {
6360             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6361         } else {
6362             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6363             if (glXMakeCurrent(implicitSwapchainImpl->display,
6364                 newContext->drawable, newContext->context) == False) {
6365
6366                 TRACE("Error in setting current context: context %p drawable %ld\n",
6367                     newContext->context, newContext->drawable);
6368             }
6369             checkGLcall("glXMakeContextCurrent");
6370
6371             /* Clean up the old context */
6372             IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
6373
6374             /* Reapply stateblock, and set device to render to a texture */
6375             device_reapply_stateblock(This);
6376             device_render_to_texture(This, TRUE);
6377
6378             /* Set the current context of the swapchain to the new context */
6379             implicitSwapchainImpl->drawable   = newContext->drawable;
6380             implicitSwapchainImpl->render_ctx = newContext->context;
6381         }
6382     } else {
6383         /* Same context, but update render_offscreen and cull mode */
6384         device_render_to_texture(This, TRUE);
6385     }
6386
6387     if (cfgs != NULL)                   XFree(cfgs);
6388     if (implicitSwapchain != NULL)       IWineD3DSwapChain_Release(implicitSwapchain);
6389     if (currentSwapchain != NULL)       IWineD3DSwapChain_Release(currentSwapchain);
6390     if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
6391     LEAVE_GL();
6392 #endif
6393     return WINED3D_OK;
6394 }
6395
6396 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6397                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6398     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6399     /* TODO: the use of Impl is deprecated. */
6400     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6401
6402     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6403
6404     /* some basic validation checks */
6405     if(This->cursorTexture) {
6406         ENTER_GL();
6407         glDeleteTextures(1, &This->cursorTexture);
6408         LEAVE_GL();
6409         This->cursorTexture = 0;
6410     }
6411
6412     if(pCursorBitmap) {
6413         /* MSDN: Cursor must be A8R8G8B8 */
6414         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6415             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6416             return WINED3DERR_INVALIDCALL;
6417         }
6418
6419         /* MSDN: Cursor must be smaller than the display mode */
6420         if(pSur->currentDesc.Width > This->ddraw_width ||
6421            pSur->currentDesc.Height > This->ddraw_height) {
6422             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);
6423             return WINED3DERR_INVALIDCALL;
6424         }
6425
6426         /* TODO: MSDN: Cursor sizes must be a power of 2 */
6427         /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
6428          * Texture and Blitting code to draw the cursor
6429          */
6430         pSur->Flags |= SFLAG_FORCELOAD;
6431         IWineD3DSurface_PreLoad(pCursorBitmap);
6432         pSur->Flags &= ~SFLAG_FORCELOAD;
6433         /* Do not store the surface's pointer because the application may release
6434          * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
6435          * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
6436          */
6437         This->cursorTexture = pSur->glDescription.textureName;
6438         This->cursorWidth = pSur->currentDesc.Width;
6439         This->cursorHeight = pSur->currentDesc.Height;
6440         pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
6441     }
6442
6443     This->xHotSpot = XHotSpot;
6444     This->yHotSpot = YHotSpot;
6445     return WINED3D_OK;
6446 }
6447
6448 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6449     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6450     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6451
6452     This->xScreenSpace = XScreenSpace;
6453     This->yScreenSpace = YScreenSpace;
6454
6455     return;
6456
6457 }
6458
6459 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6460     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6461     BOOL oldVisible = This->bCursorVisible;
6462     TRACE("(%p) : visible(%d)\n", This, bShow);
6463
6464     if(This->cursorTexture)
6465         This->bCursorVisible = bShow;
6466
6467     return oldVisible;
6468 }
6469
6470 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6471     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6472     TRACE("(%p) : state (%u)\n", This, This->state);
6473     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6474     switch (This->state) {
6475     case WINED3D_OK:
6476         return WINED3D_OK;
6477     case WINED3DERR_DEVICELOST:
6478         {
6479             ResourceList *resourceList  = This->resources;
6480             while (NULL != resourceList) {
6481                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6482                 return WINED3DERR_DEVICENOTRESET;
6483                 resourceList = resourceList->next;
6484             }
6485             return WINED3DERR_DEVICELOST;
6486         }
6487     case WINED3DERR_DRIVERINTERNALERROR:
6488         return WINED3DERR_DRIVERINTERNALERROR;
6489     }
6490
6491     /* Unknown state */
6492     return WINED3DERR_DRIVERINTERNALERROR;
6493 }
6494
6495
6496 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6497     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6498     /** FIXME: Resource tracking needs to be done,
6499     * The closes we can do to this is set the priorities of all managed textures low
6500     * and then reset them.
6501      ***********************************************************/
6502     FIXME("(%p) : stub\n", This);
6503     return WINED3D_OK;
6504 }
6505
6506 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6507     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6508     if(surface->Flags & SFLAG_DIBSECTION) {
6509         /* Release the DC */
6510         SelectObject(surface->hDC, surface->dib.holdbitmap);
6511         DeleteDC(surface->hDC);
6512         /* Release the DIB section */
6513         DeleteObject(surface->dib.DIBsection);
6514         surface->dib.bitmap_data = NULL;
6515         surface->resource.allocatedMemory = NULL;
6516         surface->Flags &= ~SFLAG_DIBSECTION;
6517     }
6518     surface->currentDesc.Width = *pPresentationParameters->BackBufferWidth;
6519     surface->currentDesc.Height = *pPresentationParameters->BackBufferHeight;
6520     if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
6521         surface->pow2Width = *pPresentationParameters->BackBufferWidth;
6522         surface->pow2Height = *pPresentationParameters->BackBufferHeight;
6523     } else {
6524         surface->pow2Width = surface->pow2Height = 1;
6525         while (surface->pow2Width < *pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6526         while (surface->pow2Height < *pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6527     }
6528     if(surface->glDescription.textureName) {
6529         ENTER_GL();
6530         glDeleteTextures(1, &surface->glDescription.textureName);
6531         LEAVE_GL();
6532         surface->glDescription.textureName = 0;
6533     }
6534     if(surface->pow2Width != *pPresentationParameters->BackBufferWidth ||
6535        surface->pow2Height != *pPresentationParameters->BackBufferHeight) {
6536         surface->Flags |= SFLAG_NONPOW2;
6537     } else  {
6538         surface->Flags &= ~SFLAG_NONPOW2;
6539     }
6540     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
6541     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6542 }
6543
6544 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6545     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6546     IWineD3DSwapChainImpl *swapchain;
6547     HRESULT hr;
6548     BOOL DisplayModeChanged = FALSE;
6549     WINED3DDISPLAYMODE mode;
6550     TRACE("(%p)\n", This);
6551
6552     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6553     if(FAILED(hr)) {
6554         ERR("Failed to get the first implicit swapchain\n");
6555         return hr;
6556     }
6557
6558     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6559      * on an existing gl context, so there's no real need for recreation.
6560      *
6561      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6562      *
6563      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6564      */
6565     TRACE("New params:\n");
6566     TRACE("BackBufferWidth = %d\n", *pPresentationParameters->BackBufferWidth);
6567     TRACE("BackBufferHeight = %d\n", *pPresentationParameters->BackBufferHeight);
6568     TRACE("BackBufferFormat = %s\n", debug_d3dformat(*pPresentationParameters->BackBufferFormat));
6569     TRACE("BackBufferCount = %d\n", *pPresentationParameters->BackBufferCount);
6570     TRACE("MultiSampleType = %d\n", *pPresentationParameters->MultiSampleType);
6571     TRACE("MultiSampleQuality = %d\n", *pPresentationParameters->MultiSampleQuality);
6572     TRACE("SwapEffect = %d\n", *pPresentationParameters->SwapEffect);
6573     TRACE("hDeviceWindow = %p\n", *pPresentationParameters->hDeviceWindow);
6574     TRACE("Windowed = %s\n", *pPresentationParameters->Windowed ? "true" : "false");
6575     TRACE("EnableAutoDepthStencil = %s\n", *pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6576     TRACE("Flags = %08x\n", *pPresentationParameters->Flags);
6577     TRACE("FullScreen_RefreshRateInHz = %d\n", *pPresentationParameters->FullScreen_RefreshRateInHz);
6578     TRACE("PresentationInterval = %d\n", *pPresentationParameters->PresentationInterval);
6579
6580     /* No special treatment of these parameters. Just store them */
6581     swapchain->presentParms.SwapEffect = *pPresentationParameters->SwapEffect;
6582     swapchain->presentParms.Flags = *pPresentationParameters->Flags;
6583     swapchain->presentParms.PresentationInterval = *pPresentationParameters->PresentationInterval;
6584     swapchain->presentParms.FullScreen_RefreshRateInHz = *pPresentationParameters->FullScreen_RefreshRateInHz;
6585
6586     /* What to do about these? */
6587     if(*pPresentationParameters->BackBufferCount != 0 &&
6588         *pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6589         ERR("Cannot change the back buffer count yet\n");
6590     }
6591     if(*pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6592         *pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6593         ERR("Cannot change the back buffer format yet\n");
6594     }
6595     if(*pPresentationParameters->hDeviceWindow != NULL &&
6596         *pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6597         ERR("Cannot change the device window yet\n");
6598     }
6599     if(*pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
6600         ERR("What do do about a changed auto depth stencil parameter?\n");
6601     }
6602
6603     if(*pPresentationParameters->Windowed) {
6604         mode.Width = swapchain->orig_width;
6605         mode.Height = swapchain->orig_height;
6606         mode.RefreshRate = 0;
6607         mode.Format = swapchain->presentParms.BackBufferFormat;
6608     } else {
6609         mode.Width = *pPresentationParameters->BackBufferWidth;
6610         mode.Height = *pPresentationParameters->BackBufferHeight;
6611         mode.RefreshRate = *pPresentationParameters->FullScreen_RefreshRateInHz;
6612         mode.Format = swapchain->presentParms.BackBufferFormat;
6613     }
6614
6615     /* Should Width == 800 && Height == 0 set 800x600? */
6616     if(*pPresentationParameters->BackBufferWidth != 0 && *pPresentationParameters->BackBufferHeight != 0 &&
6617        (*pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6618         *pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6619     {
6620         WINED3DVIEWPORT vp;
6621         int i;
6622
6623         vp.X = 0;
6624         vp.Y = 0;
6625         vp.Width = *pPresentationParameters->BackBufferWidth;
6626         vp.Height = *pPresentationParameters->BackBufferHeight;
6627         vp.MinZ = 0;
6628         vp.MaxZ = 1;
6629
6630         if(!*pPresentationParameters->Windowed) {
6631             DisplayModeChanged = TRUE;
6632         }
6633         swapchain->presentParms.BackBufferWidth = *pPresentationParameters->BackBufferWidth;
6634         swapchain->presentParms.BackBufferHeight = *pPresentationParameters->BackBufferHeight;
6635
6636         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
6637         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
6638             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
6639         }
6640
6641         /* Now set the new viewport */
6642         IWineD3DDevice_SetViewport(iface, &vp);
6643     }
6644
6645     if((*pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
6646        (swapchain->presentParms.Windowed && !*pPresentationParameters->Windowed) ||
6647         DisplayModeChanged) {
6648         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6649     }
6650
6651     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6652     return WINED3D_OK;
6653 }
6654
6655 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6656     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6657     /** FIXME: always true at the moment **/
6658     if(!bEnableDialogs) {
6659         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6660     }
6661     return WINED3D_OK;
6662 }
6663
6664
6665 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6666     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6667     TRACE("(%p) : pParameters %p\n", This, pParameters);
6668
6669     *pParameters = This->createParms;
6670     return WINED3D_OK;
6671 }
6672
6673 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6674     IWineD3DSwapChain *swapchain;
6675     HRESULT hrc = WINED3D_OK;
6676
6677     TRACE("Relaying  to swapchain\n");
6678
6679     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6680         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6681         IWineD3DSwapChain_Release(swapchain);
6682     }
6683     return;
6684 }
6685
6686 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6687     IWineD3DSwapChain *swapchain;
6688     HRESULT hrc = WINED3D_OK;
6689
6690     TRACE("Relaying  to swapchain\n");
6691
6692     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6693         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6694         IWineD3DSwapChain_Release(swapchain);
6695     }
6696     return;
6697 }
6698
6699
6700 /** ********************************************************
6701 *   Notification functions
6702 ** ********************************************************/
6703 /** This function must be called in the release of a resource when ref == 0,
6704 * the contents of resource must still be correct,
6705 * any handels to other resource held by the caller must be closed
6706 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6707  *****************************************************/
6708 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6709     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6710     ResourceList* resourceList;
6711
6712     TRACE("(%p) : resource %p\n", This, resource);
6713 #if 0
6714     EnterCriticalSection(&resourceStoreCriticalSection);
6715 #endif
6716     /* add a new texture to the frot of the linked list */
6717     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6718     resourceList->resource = resource;
6719
6720     /* Get the old head */
6721     resourceList->next = This->resources;
6722
6723     This->resources = resourceList;
6724     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6725
6726 #if 0
6727     LeaveCriticalSection(&resourceStoreCriticalSection);
6728 #endif
6729     return;
6730 }
6731
6732 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6733     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6734     ResourceList* resourceList = NULL;
6735     ResourceList* previousResourceList = NULL;
6736     
6737     TRACE("(%p) : resource %p\n", This, resource);
6738
6739 #if 0
6740     EnterCriticalSection(&resourceStoreCriticalSection);
6741 #endif
6742     resourceList = This->resources;
6743
6744     while (resourceList != NULL) {
6745         if(resourceList->resource == resource) break;
6746         previousResourceList = resourceList;
6747         resourceList = resourceList->next;
6748     }
6749
6750     if (resourceList == NULL) {
6751         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6752 #if 0
6753         LeaveCriticalSection(&resourceStoreCriticalSection);
6754 #endif
6755         return;
6756     } else {
6757             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6758     }
6759     /* make sure we don't leave a hole in the list */
6760     if (previousResourceList != NULL) {
6761         previousResourceList->next = resourceList->next;
6762     } else {
6763         This->resources = resourceList->next;
6764     }
6765
6766 #if 0
6767     LeaveCriticalSection(&resourceStoreCriticalSection);
6768 #endif
6769     return;
6770 }
6771
6772
6773 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6774     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6775     int counter;
6776
6777     TRACE("(%p) : resource %p\n", This, resource);
6778     switch(IWineD3DResource_GetType(resource)){
6779         case WINED3DRTYPE_SURFACE:
6780         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6781         break;
6782         case WINED3DRTYPE_TEXTURE:
6783         case WINED3DRTYPE_CUBETEXTURE:
6784         case WINED3DRTYPE_VOLUMETEXTURE:
6785                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
6786                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6787                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6788                         This->stateBlock->textures[counter] = NULL;
6789                     }
6790                     if (This->updateStateBlock != This->stateBlock ){
6791                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6792                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6793                             This->updateStateBlock->textures[counter] = NULL;
6794                         }
6795                     }
6796                 }
6797         break;
6798         case WINED3DRTYPE_VOLUME:
6799         /* TODO: nothing really? */
6800         break;
6801         case WINED3DRTYPE_VERTEXBUFFER:
6802         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6803         {
6804             int streamNumber;
6805             TRACE("Cleaning up stream pointers\n");
6806
6807             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6808                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6809                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6810                 */
6811                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6812                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6813                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6814                         This->updateStateBlock->streamSource[streamNumber] = 0;
6815                         /* Set changed flag? */
6816                     }
6817                 }
6818                 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) */
6819                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6820                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6821                         This->stateBlock->streamSource[streamNumber] = 0;
6822                     }
6823                 }
6824 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6825                  else { /* This shouldn't happen */
6826                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6827                 }
6828 #endif
6829
6830             }
6831         }
6832         break;
6833         case WINED3DRTYPE_INDEXBUFFER:
6834         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6835         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6836             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6837                 This->updateStateBlock->pIndexData =  NULL;
6838             }
6839         }
6840         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6841             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6842                 This->stateBlock->pIndexData =  NULL;
6843             }
6844         }
6845
6846         break;
6847         default:
6848         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6849         break;
6850     }
6851
6852
6853     /* Remove the resoruce from the resourceStore */
6854     IWineD3DDeviceImpl_RemoveResource(iface, resource);
6855
6856     TRACE("Resource released\n");
6857
6858 }
6859
6860 /**********************************************************
6861  * IWineD3DDevice VTbl follows
6862  **********************************************************/
6863
6864 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6865 {
6866     /*** IUnknown methods ***/
6867     IWineD3DDeviceImpl_QueryInterface,
6868     IWineD3DDeviceImpl_AddRef,
6869     IWineD3DDeviceImpl_Release,
6870     /*** IWineD3DDevice methods ***/
6871     IWineD3DDeviceImpl_GetParent,
6872     /*** Creation methods**/
6873     IWineD3DDeviceImpl_CreateVertexBuffer,
6874     IWineD3DDeviceImpl_CreateIndexBuffer,
6875     IWineD3DDeviceImpl_CreateStateBlock,
6876     IWineD3DDeviceImpl_CreateSurface,
6877     IWineD3DDeviceImpl_CreateTexture,
6878     IWineD3DDeviceImpl_CreateVolumeTexture,
6879     IWineD3DDeviceImpl_CreateVolume,
6880     IWineD3DDeviceImpl_CreateCubeTexture,
6881     IWineD3DDeviceImpl_CreateQuery,
6882     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6883     IWineD3DDeviceImpl_CreateVertexDeclaration,
6884     IWineD3DDeviceImpl_CreateVertexShader,
6885     IWineD3DDeviceImpl_CreatePixelShader,
6886     IWineD3DDeviceImpl_CreatePalette,
6887     /*** Odd functions **/
6888     IWineD3DDeviceImpl_Init3D,
6889     IWineD3DDeviceImpl_Uninit3D,
6890     IWineD3DDeviceImpl_SetFullscreen,
6891     IWineD3DDeviceImpl_EnumDisplayModes,
6892     IWineD3DDeviceImpl_EvictManagedResources,
6893     IWineD3DDeviceImpl_GetAvailableTextureMem,
6894     IWineD3DDeviceImpl_GetBackBuffer,
6895     IWineD3DDeviceImpl_GetCreationParameters,
6896     IWineD3DDeviceImpl_GetDeviceCaps,
6897     IWineD3DDeviceImpl_GetDirect3D,
6898     IWineD3DDeviceImpl_GetDisplayMode,
6899     IWineD3DDeviceImpl_SetDisplayMode,
6900     IWineD3DDeviceImpl_GetHWND,
6901     IWineD3DDeviceImpl_SetHWND,
6902     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6903     IWineD3DDeviceImpl_GetRasterStatus,
6904     IWineD3DDeviceImpl_GetSwapChain,
6905     IWineD3DDeviceImpl_Reset,
6906     IWineD3DDeviceImpl_SetDialogBoxMode,
6907     IWineD3DDeviceImpl_SetCursorProperties,
6908     IWineD3DDeviceImpl_SetCursorPosition,
6909     IWineD3DDeviceImpl_ShowCursor,
6910     IWineD3DDeviceImpl_TestCooperativeLevel,
6911     /*** Getters and setters **/
6912     IWineD3DDeviceImpl_SetClipPlane,
6913     IWineD3DDeviceImpl_GetClipPlane,
6914     IWineD3DDeviceImpl_SetClipStatus,
6915     IWineD3DDeviceImpl_GetClipStatus,
6916     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6917     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6918     IWineD3DDeviceImpl_SetDepthStencilSurface,
6919     IWineD3DDeviceImpl_GetDepthStencilSurface,
6920     IWineD3DDeviceImpl_SetFVF,
6921     IWineD3DDeviceImpl_GetFVF,
6922     IWineD3DDeviceImpl_SetGammaRamp,
6923     IWineD3DDeviceImpl_GetGammaRamp,
6924     IWineD3DDeviceImpl_SetIndices,
6925     IWineD3DDeviceImpl_GetIndices,
6926     IWineD3DDeviceImpl_SetLight,
6927     IWineD3DDeviceImpl_GetLight,
6928     IWineD3DDeviceImpl_SetLightEnable,
6929     IWineD3DDeviceImpl_GetLightEnable,
6930     IWineD3DDeviceImpl_SetMaterial,
6931     IWineD3DDeviceImpl_GetMaterial,
6932     IWineD3DDeviceImpl_SetNPatchMode,
6933     IWineD3DDeviceImpl_GetNPatchMode,
6934     IWineD3DDeviceImpl_SetPaletteEntries,
6935     IWineD3DDeviceImpl_GetPaletteEntries,
6936     IWineD3DDeviceImpl_SetPixelShader,
6937     IWineD3DDeviceImpl_GetPixelShader,
6938     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6939     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6940     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6941     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6942     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6943     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6944     IWineD3DDeviceImpl_SetRenderState,
6945     IWineD3DDeviceImpl_GetRenderState,
6946     IWineD3DDeviceImpl_SetRenderTarget,
6947     IWineD3DDeviceImpl_GetRenderTarget,
6948     IWineD3DDeviceImpl_SetFrontBackBuffers,
6949     IWineD3DDeviceImpl_SetSamplerState,
6950     IWineD3DDeviceImpl_GetSamplerState,
6951     IWineD3DDeviceImpl_SetScissorRect,
6952     IWineD3DDeviceImpl_GetScissorRect,
6953     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6954     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6955     IWineD3DDeviceImpl_SetStreamSource,
6956     IWineD3DDeviceImpl_GetStreamSource,
6957     IWineD3DDeviceImpl_SetStreamSourceFreq,
6958     IWineD3DDeviceImpl_GetStreamSourceFreq,
6959     IWineD3DDeviceImpl_SetTexture,
6960     IWineD3DDeviceImpl_GetTexture,
6961     IWineD3DDeviceImpl_SetTextureStageState,
6962     IWineD3DDeviceImpl_GetTextureStageState,
6963     IWineD3DDeviceImpl_SetTransform,
6964     IWineD3DDeviceImpl_GetTransform,
6965     IWineD3DDeviceImpl_SetVertexDeclaration,
6966     IWineD3DDeviceImpl_GetVertexDeclaration,
6967     IWineD3DDeviceImpl_SetVertexShader,
6968     IWineD3DDeviceImpl_GetVertexShader,
6969     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6970     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6971     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6972     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6973     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6974     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6975     IWineD3DDeviceImpl_SetViewport,
6976     IWineD3DDeviceImpl_GetViewport,
6977     IWineD3DDeviceImpl_MultiplyTransform,
6978     IWineD3DDeviceImpl_ValidateDevice,
6979     IWineD3DDeviceImpl_ProcessVertices,
6980     /*** State block ***/
6981     IWineD3DDeviceImpl_BeginStateBlock,
6982     IWineD3DDeviceImpl_EndStateBlock,
6983     /*** Scene management ***/
6984     IWineD3DDeviceImpl_BeginScene,
6985     IWineD3DDeviceImpl_EndScene,
6986     IWineD3DDeviceImpl_Present,
6987     IWineD3DDeviceImpl_Clear,
6988     /*** Drawing ***/
6989     IWineD3DDeviceImpl_DrawPrimitive,
6990     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6991     IWineD3DDeviceImpl_DrawPrimitiveUP,
6992     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6993     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6994     IWineD3DDeviceImpl_DrawRectPatch,
6995     IWineD3DDeviceImpl_DrawTriPatch,
6996     IWineD3DDeviceImpl_DeletePatch,
6997     IWineD3DDeviceImpl_ColorFill,
6998     IWineD3DDeviceImpl_UpdateTexture,
6999     IWineD3DDeviceImpl_UpdateSurface,
7000     IWineD3DDeviceImpl_StretchRect,
7001     IWineD3DDeviceImpl_GetRenderTargetData,
7002     IWineD3DDeviceImpl_GetFrontBufferData,
7003     /*** Internal use IWineD3DDevice methods ***/
7004     IWineD3DDeviceImpl_SetupTextureStates,
7005     /*** object tracking ***/
7006     IWineD3DDeviceImpl_ResourceReleased
7007 };
7008
7009
7010 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7011     WINED3DRS_ALPHABLENDENABLE   ,
7012     WINED3DRS_ALPHAFUNC          ,
7013     WINED3DRS_ALPHAREF           ,
7014     WINED3DRS_ALPHATESTENABLE    ,
7015     WINED3DRS_BLENDOP            ,
7016     WINED3DRS_COLORWRITEENABLE   ,
7017     WINED3DRS_DESTBLEND          ,
7018     WINED3DRS_DITHERENABLE       ,
7019     WINED3DRS_FILLMODE           ,
7020     WINED3DRS_FOGDENSITY         ,
7021     WINED3DRS_FOGEND             ,
7022     WINED3DRS_FOGSTART           ,
7023     WINED3DRS_LASTPIXEL          ,
7024     WINED3DRS_SHADEMODE          ,
7025     WINED3DRS_SRCBLEND           ,
7026     WINED3DRS_STENCILENABLE      ,
7027     WINED3DRS_STENCILFAIL        ,
7028     WINED3DRS_STENCILFUNC        ,
7029     WINED3DRS_STENCILMASK        ,
7030     WINED3DRS_STENCILPASS        ,
7031     WINED3DRS_STENCILREF         ,
7032     WINED3DRS_STENCILWRITEMASK   ,
7033     WINED3DRS_STENCILZFAIL       ,
7034     WINED3DRS_TEXTUREFACTOR      ,
7035     WINED3DRS_WRAP0              ,
7036     WINED3DRS_WRAP1              ,
7037     WINED3DRS_WRAP2              ,
7038     WINED3DRS_WRAP3              ,
7039     WINED3DRS_WRAP4              ,
7040     WINED3DRS_WRAP5              ,
7041     WINED3DRS_WRAP6              ,
7042     WINED3DRS_WRAP7              ,
7043     WINED3DRS_ZENABLE            ,
7044     WINED3DRS_ZFUNC              ,
7045     WINED3DRS_ZWRITEENABLE
7046 };
7047
7048 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7049     WINED3DTSS_ADDRESSW              ,
7050     WINED3DTSS_ALPHAARG0             ,
7051     WINED3DTSS_ALPHAARG1             ,
7052     WINED3DTSS_ALPHAARG2             ,
7053     WINED3DTSS_ALPHAOP               ,
7054     WINED3DTSS_BUMPENVLOFFSET        ,
7055     WINED3DTSS_BUMPENVLSCALE         ,
7056     WINED3DTSS_BUMPENVMAT00          ,
7057     WINED3DTSS_BUMPENVMAT01          ,
7058     WINED3DTSS_BUMPENVMAT10          ,
7059     WINED3DTSS_BUMPENVMAT11          ,
7060     WINED3DTSS_COLORARG0             ,
7061     WINED3DTSS_COLORARG1             ,
7062     WINED3DTSS_COLORARG2             ,
7063     WINED3DTSS_COLOROP               ,
7064     WINED3DTSS_RESULTARG             ,
7065     WINED3DTSS_TEXCOORDINDEX         ,
7066     WINED3DTSS_TEXTURETRANSFORMFLAGS
7067 };
7068
7069 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7070     WINED3DSAMP_ADDRESSU         ,
7071     WINED3DSAMP_ADDRESSV         ,
7072     WINED3DSAMP_ADDRESSW         ,
7073     WINED3DSAMP_BORDERCOLOR      ,
7074     WINED3DSAMP_MAGFILTER        ,
7075     WINED3DSAMP_MINFILTER        ,
7076     WINED3DSAMP_MIPFILTER        ,
7077     WINED3DSAMP_MIPMAPLODBIAS    ,
7078     WINED3DSAMP_MAXMIPLEVEL      ,
7079     WINED3DSAMP_MAXANISOTROPY    ,
7080     WINED3DSAMP_SRGBTEXTURE      ,
7081     WINED3DSAMP_ELEMENTINDEX
7082 };
7083
7084 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7085     WINED3DRS_AMBIENT                       ,
7086     WINED3DRS_AMBIENTMATERIALSOURCE         ,
7087     WINED3DRS_CLIPPING                      ,
7088     WINED3DRS_CLIPPLANEENABLE               ,
7089     WINED3DRS_COLORVERTEX                   ,
7090     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
7091     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
7092     WINED3DRS_FOGDENSITY                    ,
7093     WINED3DRS_FOGEND                        ,
7094     WINED3DRS_FOGSTART                      ,
7095     WINED3DRS_FOGTABLEMODE                  ,
7096     WINED3DRS_FOGVERTEXMODE                 ,
7097     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
7098     WINED3DRS_LIGHTING                      ,
7099     WINED3DRS_LOCALVIEWER                   ,
7100     WINED3DRS_MULTISAMPLEANTIALIAS          ,
7101     WINED3DRS_MULTISAMPLEMASK               ,
7102     WINED3DRS_NORMALIZENORMALS              ,
7103     WINED3DRS_PATCHEDGESTYLE                ,
7104     WINED3DRS_POINTSCALE_A                  ,
7105     WINED3DRS_POINTSCALE_B                  ,
7106     WINED3DRS_POINTSCALE_C                  ,
7107     WINED3DRS_POINTSCALEENABLE              ,
7108     WINED3DRS_POINTSIZE                     ,
7109     WINED3DRS_POINTSIZE_MAX                 ,
7110     WINED3DRS_POINTSIZE_MIN                 ,
7111     WINED3DRS_POINTSPRITEENABLE             ,
7112     WINED3DRS_RANGEFOGENABLE                ,
7113     WINED3DRS_SPECULARMATERIALSOURCE        ,
7114     WINED3DRS_TWEENFACTOR                   ,
7115     WINED3DRS_VERTEXBLEND
7116 };
7117
7118 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7119     WINED3DTSS_TEXCOORDINDEX         ,
7120     WINED3DTSS_TEXTURETRANSFORMFLAGS
7121 };
7122
7123 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7124     WINED3DSAMP_DMAPOFFSET
7125 };
7126
7127 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
7128     DWORD rep = StateTable[state].representative;
7129     DWORD idx;
7130     BYTE shift;
7131
7132     if(!rep || isStateDirty(This, rep)) return;
7133
7134     This->dirtyArray[This->numDirtyEntries++] = rep;
7135     idx = rep >> 5;
7136     shift = rep & 0x1f;
7137     This->isStateDirty[idx] |= (1 << shift);
7138 }