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