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