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