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