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