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