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