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