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