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