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