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