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