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