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