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