janitorial: Remove remaining NULL checks before free() (found by Smatch).
[wine] / dlls / wined3d / device.c
1 /*
2  * IWineD3DDevice implementation
3  *
4  * Copyright 2002 Lionel Ulmer
5  * Copyright 2002-2005 Jason Edmeades
6  * Copyright 2003-2004 Raphael Junqueira
7  * Copyright 2004 Christian Costa
8  * Copyright 2005 Oliver Stieber
9  * Copyright 2006 Stefan Dösinger for CodeWeavers
10  * Copyright 2006 Henri Verbeet
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include <stdio.h>
29 #ifdef HAVE_FLOAT_H
30 # include <float.h>
31 #endif
32 #include "wined3d_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
37
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light = {
40
41     D3DLIGHT_DIRECTIONAL,    /* Type */
42     { 1.0, 1.0, 1.0, 0.0 },  /* Diffuse r,g,b,a */
43     { 0.0, 0.0, 0.0, 0.0 },  /* Specular r,g,b,a */
44     { 0.0, 0.0, 0.0, 0.0 },  /* Ambient r,g,b,a, */
45     { 0.0, 0.0, 0.0 },       /* Position x,y,z */
46     { 0.0, 0.0, 1.0 },       /* Direction x,y,z */
47     0.0,                     /* Range */
48     0.0,                     /* Falloff */
49     0.0, 0.0, 0.0,           /* Attenuation 0,1,2 */
50     0.0,                     /* Theta */
51     0.0                      /* Phi */
52 };
53
54 /* x11drv GDI escapes */
55 #define X11DRV_ESCAPE 6789
56 enum x11drv_escape_codes
57 {
58     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
59     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
60     X11DRV_GET_FONT,      /* get current X font for a DC */
61 };
62
63 /* retrieve the X display to use on a given DC */
64 inline static Display *get_display( HDC hdc )
65 {
66     Display *display;
67     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
68
69     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
70                     sizeof(display), (LPSTR)&display )) display = NULL;
71     return display;
72 }
73
74 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
75 /* enable pbuffer support for offscreen textures */
76 BOOL pbuffer_support     = FALSE;
77 /* allocate one pbuffer per surface */
78 BOOL pbuffer_per_surface = FALSE;
79
80 /* static function declarations */
81 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
82
83 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type);
84
85 /* helper macros */
86 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
87
88 #define D3DCREATEOBJECTINSTANCE(object, type) { \
89     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
90     D3DMEMCHECK(object, pp##type); \
91     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
92     object->wineD3DDevice = This; \
93     object->parent       = parent; \
94     object->ref          = 1; \
95     *pp##type = (IWineD3D##type *) object; \
96 }
97
98 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
99     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
100     D3DMEMCHECK(object, pp##type); \
101     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
102     object->parent       = parent; \
103     object->ref          = 1; \
104     object->baseShader.device = (IWineD3DDevice*) This; \
105     *pp##type = (IWineD3D##type *) object; \
106 }
107
108 #define  D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
109     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
110     D3DMEMCHECK(object, pp##type); \
111     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
112     object->resource.wineD3DDevice   = This; \
113     object->resource.parent          = parent; \
114     object->resource.resourceType    = d3dtype; \
115     object->resource.ref             = 1; \
116     object->resource.pool            = Pool; \
117     object->resource.format          = Format; \
118     object->resource.usage           = Usage; \
119     object->resource.size            = _size; \
120     /* Check that we have enough video ram left */ \
121     if (Pool == WINED3DPOOL_DEFAULT) { \
122         if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
123             WARN("Out of 'bogus' video memory\n"); \
124             HeapFree(GetProcessHeap(), 0, object); \
125             *pp##type = NULL; \
126             return WINED3DERR_OUTOFVIDEOMEMORY; \
127         } \
128         globalChangeGlRam(_size); \
129     } \
130     object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
131     if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
132         FIXME("Out of memory!\n"); \
133         HeapFree(GetProcessHeap(), 0, object); \
134         *pp##type = NULL; \
135         return WINED3DERR_OUTOFVIDEOMEMORY; \
136     } \
137     *pp##type = (IWineD3D##type *) object; \
138     IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
139     TRACE("(%p) : Created resource %p\n", This, object); \
140 }
141
142 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
143     _basetexture.levels     = Levels; \
144     _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
145     _basetexture.LOD        = 0; \
146     _basetexture.dirty      = TRUE; \
147 }
148
149 /**********************************************************
150  * Global variable / Constants follow
151  **********************************************************/
152 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
153
154 /**********************************************************
155  * Utility functions follow
156  **********************************************************/
157 /* Convert the D3DLIGHT properties into equivalent gl lights */
158 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
159
160     float quad_att;
161     float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
162     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
163
164     /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
165     glMatrixMode(GL_MODELVIEW);
166     glPushMatrix();
167     glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
168
169     /* Diffuse: */
170     colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
171     colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
172     colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
173     colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
174     glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
175     checkGLcall("glLightfv");
176
177     /* Specular */
178     colRGBA[0] = lightInfo->OriginalParms.Specular.r;
179     colRGBA[1] = lightInfo->OriginalParms.Specular.g;
180     colRGBA[2] = lightInfo->OriginalParms.Specular.b;
181     colRGBA[3] = lightInfo->OriginalParms.Specular.a;
182     glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
183     checkGLcall("glLightfv");
184
185     /* Ambient */
186     colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
187     colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
188     colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
189     colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
190     glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
191     checkGLcall("glLightfv");
192
193     /* Attenuation - Are these right? guessing... */
194     glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
195     checkGLcall("glLightf");
196     glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
197     checkGLcall("glLightf");
198
199     if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
200         quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
201     } else {
202         quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
203     }
204
205     if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
206     glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
207     checkGLcall("glLightf");
208
209     switch (lightInfo->OriginalParms.Type) {
210     case D3DLIGHT_POINT:
211         /* Position */
212         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
213         checkGLcall("glLightfv");
214         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
215         checkGLcall("glLightf");
216         /* FIXME: Range */
217         break;
218
219     case D3DLIGHT_SPOT:
220         /* Position */
221         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
222         checkGLcall("glLightfv");
223         /* Direction */
224         glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
225         checkGLcall("glLightfv");
226         glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
227         checkGLcall("glLightf");
228         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
229         checkGLcall("glLightf");
230         /* FIXME: Range */
231         break;
232
233     case D3DLIGHT_DIRECTIONAL:
234         /* Direction */
235         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
236         checkGLcall("glLightfv");
237         glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
238         checkGLcall("glLightf");
239         glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
240         checkGLcall("glLightf");
241         break;
242
243     default:
244         FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
245     }
246
247     /* Restore the modelview matrix */
248     glPopMatrix();
249 }
250
251 /**********************************************************
252  * GLSL helper functions follow
253  **********************************************************/
254
255 /** Attach a GLSL pixel or vertex shader object to the shader program */
256 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
257
258     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
259     GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
260     if (This->stateBlock->glsl_program && shaderObj != 0) {
261         TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
262         GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
263         checkGLcall("glAttachObjectARB");
264     }
265 }
266
267 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
268  * It sets the programId on the current StateBlock (because it should be called
269  * inside of the DrawPrimitive() part of the render loop).
270  *
271  * If a program for the given combination does not exist, create one, and store
272  * the program in the list.  If it creates a program, it will link the given 
273  * objects, too.
274  * 
275  * We keep the shader programs around on a list because linking
276  * shader objects together is an expensive operation.  It's much
277  * faster to loop through a list of pre-compiled & linked programs
278  * each time that the application sets a new pixel or vertex shader
279  * than it is to re-link them together at that time.
280  *
281  * The list will be deleted in IWineD3DDevice::Release().
282  */
283 void set_glsl_shader_program(IWineD3DDevice *iface) {
284
285     IWineD3DDeviceImpl *This               = (IWineD3DDeviceImpl *)iface;
286     IWineD3DPixelShader  *pshader          = This->stateBlock->pixelShader;
287     IWineD3DVertexShader *vshader          = This->stateBlock->vertexShader;
288     struct glsl_shader_prog_link *curLink  = NULL;
289     struct glsl_shader_prog_link *newLink  = NULL;
290     struct list *ptr                       = NULL;
291     GLhandleARB programId                  = 0;
292     int i;
293     char glsl_name[8];
294     
295     ptr = list_head( &This->glsl_shader_progs );
296     while (ptr) {
297         /* At least one program exists - see if it matches our ps/vs combination */
298         curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
299         if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
300             /* Existing Program found, use it */
301             TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n", 
302                    curLink->programId);
303             This->stateBlock->glsl_program = curLink;
304             return;
305         }
306         /* This isn't the entry we need - try the next one */
307         ptr = list_next( &This->glsl_shader_progs, ptr );
308     }
309
310     /* If we get to this point, then no matching program exists, so we create one */
311     programId = GL_EXTCALL(glCreateProgramObjectARB());
312     TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId);
313
314     /* Allocate a new link for the list of programs */
315     newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
316     newLink->programId    = programId;
317     This->stateBlock->glsl_program = newLink;
318    
319     /* Attach GLSL vshader */ 
320     if (NULL != vshader && 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 locablility have been debugged properly
1068     * this function is too deap to need to care about things like this.
1069     * Levels need to be checked too, and possibly Type wince they all affect what can be done.
1070     * ****************************************/
1071     switch(Pool) {
1072     case WINED3DPOOL_SCRATCH:
1073         if(!Lockable)
1074             FIXME("Create suface 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 get's 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 D3DFMT_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 D3DFMT_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 it's 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 D3DFMT_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 D3DQUERYTYPE_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 D3DQUERYTYPE_VCACHE:
1457     case D3DQUERYTYPE_RESOURCEMANAGER:
1458     case D3DQUERYTYPE_VERTEXSTATS:
1459     case D3DQUERYTYPE_EVENT:
1460     case D3DQUERYTYPE_TIMESTAMP:
1461     case D3DQUERYTYPE_TIMESTAMPDISJOINT:
1462     case D3DQUERYTYPE_TIMESTAMPFREQ:
1463     case D3DQUERYTYPE_PIPELINETIMINGS:
1464     case D3DQUERYTYPE_INTERFACETIMINGS:
1465     case D3DQUERYTYPE_VERTEXTIMINGS:
1466     case D3DQUERYTYPE_PIXELTIMINGS:
1467     case D3DQUERYTYPE_BANDWIDTHTIMINGS:
1468     case D3DQUERYTYPE_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 simila 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         D3DVIEWPORT9 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, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* 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(D3DMATRIX));
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(D3DMATRIX))) {
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, D3DTRANSFORMSTATETYPE State, D3DMATRIX* 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(D3DMATRIX));
2617     return WINED3D_OK;
2618 }
2619
2620 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2621     D3DMATRIX *mat = NULL;
2622     D3DMATRIX 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, (D3DMATRIX *) 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  *   WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2648  *****/
2649 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2650    you can reference any indexes you want as long as that number max are enabled at any
2651    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2652    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2653    but when recording, just build a chain pretty much of commands to be replayed.                  */
2654
2655 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2656     float rho;
2657     PLIGHTINFOEL *object, *temp;
2658
2659     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2660     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2661
2662     /* If recording state block, just add to end of lights chain */
2663     if (This->isRecordingState) {
2664         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2665         if (NULL == object) {
2666             return WINED3DERR_OUTOFVIDEOMEMORY;
2667         }
2668         memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2669         object->OriginalIndex = Index;
2670         object->glIndex = -1;
2671         object->changed = TRUE;
2672
2673         /* Add to the END of the chain of lights changes to be replayed */
2674         if (This->updateStateBlock->lights == NULL) {
2675             This->updateStateBlock->lights = object;
2676         } else {
2677             temp = This->updateStateBlock->lights;
2678             while (temp->next != NULL) temp=temp->next;
2679             temp->next = object;
2680         }
2681         TRACE("Recording... not performing anything more\n");
2682         return WINED3D_OK;
2683     }
2684
2685     /* Ok, not recording any longer so do real work */
2686     object = This->stateBlock->lights;
2687     while (object != NULL && object->OriginalIndex != Index) object = object->next;
2688
2689     /* If we didn't find it in the list of lights, time to add it */
2690     if (object == NULL) {
2691         PLIGHTINFOEL *insertAt,*prevPos;
2692
2693         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2694         if (NULL == object) {
2695             return WINED3DERR_OUTOFVIDEOMEMORY;
2696         }
2697         object->OriginalIndex = Index;
2698         object->glIndex = -1;
2699
2700         /* Add it to the front of list with the idea that lights will be changed as needed
2701            BUT after any lights currently assigned GL indexes                             */
2702         insertAt = This->stateBlock->lights;
2703         prevPos  = NULL;
2704         while (insertAt != NULL && insertAt->glIndex != -1) {
2705             prevPos  = insertAt;
2706             insertAt = insertAt->next;
2707         }
2708
2709         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2710             This->stateBlock->lights = object;
2711         } else if (insertAt == NULL) { /* End of list */
2712             prevPos->next = object;
2713             object->prev = prevPos;
2714         } else { /* Middle of chain */
2715             if (prevPos == NULL) {
2716                 This->stateBlock->lights = object;
2717             } else {
2718                 prevPos->next = object;
2719             }
2720             object->prev = prevPos;
2721             object->next = insertAt;
2722             insertAt->prev = object;
2723         }
2724     }
2725
2726     /* Initialize the object */
2727     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,
2728           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2729           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2730           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2731     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2732           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2733     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2734
2735     /* Save away the information */
2736     memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
2737
2738     switch (pLight->Type) {
2739     case D3DLIGHT_POINT:
2740         /* Position */
2741         object->lightPosn[0] = pLight->Position.x;
2742         object->lightPosn[1] = pLight->Position.y;
2743         object->lightPosn[2] = pLight->Position.z;
2744         object->lightPosn[3] = 1.0f;
2745         object->cutoff = 180.0f;
2746         /* FIXME: Range */
2747         break;
2748
2749     case D3DLIGHT_DIRECTIONAL:
2750         /* Direction */
2751         object->lightPosn[0] = -pLight->Direction.x;
2752         object->lightPosn[1] = -pLight->Direction.y;
2753         object->lightPosn[2] = -pLight->Direction.z;
2754         object->lightPosn[3] = 0.0;
2755         object->exponent     = 0.0f;
2756         object->cutoff       = 180.0f;
2757         break;
2758
2759     case D3DLIGHT_SPOT:
2760         /* Position */
2761         object->lightPosn[0] = pLight->Position.x;
2762         object->lightPosn[1] = pLight->Position.y;
2763         object->lightPosn[2] = pLight->Position.z;
2764         object->lightPosn[3] = 1.0;
2765
2766         /* Direction */
2767         object->lightDirn[0] = pLight->Direction.x;
2768         object->lightDirn[1] = pLight->Direction.y;
2769         object->lightDirn[2] = pLight->Direction.z;
2770         object->lightDirn[3] = 1.0;
2771
2772         /*
2773          * opengl-ish and d3d-ish spot lights use too different models for the
2774          * light "intensity" as a function of the angle towards the main light direction,
2775          * so we only can approximate very roughly.
2776          * however spot lights are rather rarely used in games (if ever used at all).
2777          * furthermore if still used, probably nobody pays attention to such details.
2778          */
2779         if (pLight->Falloff == 0) {
2780             rho = 6.28f;
2781         } else {
2782             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2783         }
2784         if (rho < 0.0001) rho = 0.0001f;
2785         object->exponent = -0.3/log(cos(rho/2));
2786         if (object->exponent > 128.0) {
2787                 object->exponent = 128.0;
2788         }
2789         object->cutoff = pLight->Phi*90/M_PI;
2790
2791         /* FIXME: Range */
2792         break;
2793
2794     default:
2795         FIXME("Unrecognized light type %d\n", pLight->Type);
2796     }
2797
2798     /* Update the live definitions if the light is currently assigned a glIndex */
2799     if (object->glIndex != -1) {
2800         setup_light(iface, object->glIndex, object);
2801     }
2802     return WINED3D_OK;
2803 }
2804
2805 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2806     PLIGHTINFOEL *lightInfo = NULL;
2807     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2808     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2809
2810     /* Locate the light in the live lights */
2811     lightInfo = This->stateBlock->lights;
2812     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2813
2814     if (lightInfo == NULL) {
2815         TRACE("Light information requested but light not defined\n");
2816         return WINED3DERR_INVALIDCALL;
2817     }
2818
2819     memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
2820     return WINED3D_OK;
2821 }
2822
2823 /*****
2824  * Get / Set Light Enable
2825  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2826  *****/
2827 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2828     PLIGHTINFOEL *lightInfo = NULL;
2829     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2830     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2831
2832     /* Tests show true = 128...not clear why */
2833
2834     Enable = Enable? 128: 0;
2835
2836     /* If recording state block, just add to end of lights chain with changedEnable set to true */
2837     if (This->isRecordingState) {
2838         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2839         if (NULL == lightInfo) {
2840             return WINED3DERR_OUTOFVIDEOMEMORY;
2841         }
2842         lightInfo->OriginalIndex = Index;
2843         lightInfo->glIndex = -1;
2844         lightInfo->enabledChanged = TRUE;
2845         lightInfo->lightEnabled = Enable;
2846
2847         /* Add to the END of the chain of lights changes to be replayed */
2848         if (This->updateStateBlock->lights == NULL) {
2849             This->updateStateBlock->lights = lightInfo;
2850         } else {
2851             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2852             while (temp->next != NULL) temp=temp->next;
2853             temp->next = lightInfo;
2854         }
2855         TRACE("Recording... not performing anything more\n");
2856         return WINED3D_OK;
2857     }
2858
2859     /* Not recording... So, locate the light in the live lights */
2860     lightInfo = This->stateBlock->lights;
2861     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2862
2863     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2864     if (lightInfo == NULL) {
2865
2866         TRACE("Light enabled requested but light not defined, so defining one!\n");
2867         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2868
2869         /* Search for it again! Should be fairly quick as near head of list */
2870         lightInfo = This->stateBlock->lights;
2871         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2872         if (lightInfo == NULL) {
2873             FIXME("Adding default lights has failed dismally\n");
2874             return WINED3DERR_INVALIDCALL;
2875         }
2876     }
2877
2878     /* OK, we now have a light... */
2879     if (!Enable) {
2880
2881         /* If we are disabling it, check it was enabled, and
2882            still only do something if it has assigned a glIndex (which it should have!)   */
2883         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2884             TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2885             ENTER_GL();
2886             glDisable(GL_LIGHT0 + lightInfo->glIndex);
2887             checkGLcall("glDisable GL_LIGHT0+Index");
2888             LEAVE_GL();
2889         } else {
2890             TRACE("Nothing to do as light was not enabled\n");
2891         }
2892         lightInfo->lightEnabled = Enable;
2893     } else {
2894
2895         /* We are enabling it. If it is enabled, it's really simple */
2896         if (lightInfo->lightEnabled) {
2897             /* nop */
2898             TRACE("Nothing to do as light was enabled\n");
2899
2900         /* If it already has a glIndex, it's still simple */
2901         } else if (lightInfo->glIndex != -1) {
2902             TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2903             lightInfo->lightEnabled = Enable;
2904             ENTER_GL();
2905             glEnable(GL_LIGHT0 + lightInfo->glIndex);
2906             checkGLcall("glEnable GL_LIGHT0+Index already setup");
2907             LEAVE_GL();
2908
2909         /* Otherwise got to find space - lights are ordered gl indexes first */
2910         } else {
2911             PLIGHTINFOEL *bsf  = NULL;
2912             PLIGHTINFOEL *pos  = This->stateBlock->lights;
2913             PLIGHTINFOEL *prev = NULL;
2914             int           Index= 0;
2915             int           glIndex = -1;
2916
2917             /* Try to minimize changes as much as possible */
2918             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2919
2920                 /* Try to remember which index can be replaced if necessary */
2921                 if (bsf==NULL && !pos->lightEnabled) {
2922                     /* Found a light we can replace, save as best replacement */
2923                     bsf = pos;
2924                 }
2925
2926                 /* Step to next space */
2927                 prev = pos;
2928                 pos = pos->next;
2929                 Index ++;
2930             }
2931
2932             /* If we have too many active lights, fail the call */
2933             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2934                 FIXME("Program requests too many concurrent lights\n");
2935                 return WINED3DERR_INVALIDCALL;
2936
2937             /* If we have allocated all lights, but not all are enabled,
2938                reuse one which is not enabled                           */
2939             } else if (Index == This->maxConcurrentLights) {
2940                 /* use bsf - Simply swap the new light and the BSF one */
2941                 PLIGHTINFOEL *bsfNext = bsf->next;
2942                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2943
2944                 /* Sort out ends */
2945                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2946                 if (bsf->prev != NULL) {
2947                     bsf->prev->next = lightInfo;
2948                 } else {
2949                     This->stateBlock->lights = lightInfo;
2950                 }
2951
2952                 /* If not side by side, lots of chains to update */
2953                 if (bsf->next != lightInfo) {
2954                     lightInfo->prev->next = bsf;
2955                     bsf->next->prev = lightInfo;
2956                     bsf->next       = lightInfo->next;
2957                     bsf->prev       = lightInfo->prev;
2958                     lightInfo->next = bsfNext;
2959                     lightInfo->prev = bsfPrev;
2960
2961                 } else {
2962                     /* Simple swaps */
2963                     bsf->prev = lightInfo;
2964                     bsf->next = lightInfo->next;
2965                     lightInfo->next = bsf;
2966                     lightInfo->prev = bsfPrev;
2967                 }
2968
2969
2970                 /* Update states */
2971                 glIndex = bsf->glIndex;
2972                 bsf->glIndex = -1;
2973                 lightInfo->glIndex = glIndex;
2974                 lightInfo->lightEnabled = Enable;
2975
2976                 /* Finally set up the light in gl itself */
2977                 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
2978                 ENTER_GL();
2979                 setup_light(iface, glIndex, lightInfo);
2980                 glEnable(GL_LIGHT0 + glIndex);
2981                 checkGLcall("glEnable GL_LIGHT0 new setup");
2982                 LEAVE_GL();
2983
2984             /* If we reached the end of the allocated lights, with space in the
2985                gl lights, setup a new light                                     */
2986             } else if (pos->glIndex == -1) {
2987
2988                 /* We reached the end of the allocated gl lights, so already
2989                     know the index of the next one!                          */
2990                 glIndex = Index;
2991                 lightInfo->glIndex = glIndex;
2992                 lightInfo->lightEnabled = Enable;
2993
2994                 /* In an ideal world, it's already in the right place */
2995                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2996                    /* No need to move it */
2997                 } else {
2998                     /* Remove this light from the list */
2999                     lightInfo->prev->next = lightInfo->next;
3000                     if (lightInfo->next != NULL) {
3001                         lightInfo->next->prev = lightInfo->prev;
3002                     }
3003
3004                     /* Add in at appropriate place (inbetween prev and pos) */
3005                     lightInfo->prev = prev;
3006                     lightInfo->next = pos;
3007                     if (prev == NULL) {
3008                         This->stateBlock->lights = lightInfo;
3009                     } else {
3010                         prev->next = lightInfo;
3011                     }
3012                     if (pos != NULL) {
3013                         pos->prev = lightInfo;
3014                     }
3015                 }
3016
3017                 /* Finally set up the light in gl itself */
3018                 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
3019                 ENTER_GL();
3020                 setup_light(iface, glIndex, lightInfo);
3021                 glEnable(GL_LIGHT0 + glIndex);
3022                 checkGLcall("glEnable GL_LIGHT0 new setup");
3023                 LEAVE_GL();
3024
3025             }
3026         }
3027     }
3028     return WINED3D_OK;
3029 }
3030
3031 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
3032
3033     PLIGHTINFOEL *lightInfo = NULL;
3034     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3035     TRACE("(%p) : for idx(%d)\n", This, Index);
3036
3037     /* Locate the light in the live lights */
3038     lightInfo = This->stateBlock->lights;
3039     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
3040
3041     if (lightInfo == NULL) {
3042         TRACE("Light enabled state requested but light not defined\n");
3043         return WINED3DERR_INVALIDCALL;
3044     }
3045     *pEnable = lightInfo->lightEnabled;
3046     return WINED3D_OK;
3047 }
3048
3049 /*****
3050  * Get / Set Clip Planes
3051  *****/
3052 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
3053     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3054     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
3055
3056     /* Validate Index */
3057     if (Index >= GL_LIMITS(clipplanes)) {
3058         TRACE("Application has requested clipplane this device doesn't support\n");
3059         return WINED3DERR_INVALIDCALL;
3060     }
3061
3062     This->updateStateBlock->changed.clipplane[Index] = TRUE;
3063     This->updateStateBlock->set.clipplane[Index] = TRUE;
3064     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3065     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3066     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3067     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3068
3069     /* Handle recording of state blocks */
3070     if (This->isRecordingState) {
3071         TRACE("Recording... not performing anything\n");
3072         return WINED3D_OK;
3073     }
3074
3075     /* Apply it */
3076
3077     ENTER_GL();
3078
3079     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3080     glMatrixMode(GL_MODELVIEW);
3081     glPushMatrix();
3082     glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3083
3084     TRACE("Clipplane [%f,%f,%f,%f]\n",
3085           This->updateStateBlock->clipplane[Index][0],
3086           This->updateStateBlock->clipplane[Index][1],
3087           This->updateStateBlock->clipplane[Index][2],
3088           This->updateStateBlock->clipplane[Index][3]);
3089     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
3090     checkGLcall("glClipPlane");
3091
3092     glPopMatrix();
3093     LEAVE_GL();
3094
3095     return WINED3D_OK;
3096 }
3097
3098 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3099     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3100     TRACE("(%p) : for idx %d\n", This, Index);
3101
3102     /* Validate Index */
3103     if (Index >= GL_LIMITS(clipplanes)) {
3104         TRACE("Application has requested clipplane this device doesn't support\n");
3105         return WINED3DERR_INVALIDCALL;
3106     }
3107
3108     pPlane[0] = This->stateBlock->clipplane[Index][0];
3109     pPlane[1] = This->stateBlock->clipplane[Index][1];
3110     pPlane[2] = This->stateBlock->clipplane[Index][2];
3111     pPlane[3] = This->stateBlock->clipplane[Index][3];
3112     return WINED3D_OK;
3113 }
3114
3115 /*****
3116  * Get / Set Clip Plane Status
3117  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3118  *****/
3119 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3120     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3121     FIXME("(%p) : stub\n", This);
3122     if (NULL == pClipStatus) {
3123       return WINED3DERR_INVALIDCALL;
3124     }
3125     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3126     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3127     return WINED3D_OK;
3128 }
3129
3130 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3131     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3132     FIXME("(%p) : stub\n", This);
3133     if (NULL == pClipStatus) {
3134       return WINED3DERR_INVALIDCALL;
3135     }
3136     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3137     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3138     return WINED3D_OK;
3139 }
3140
3141 /*****
3142  * Get / Set Material
3143  *   WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
3144  *****/
3145 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3146     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3147
3148     This->updateStateBlock->changed.material = TRUE;
3149     This->updateStateBlock->set.material = TRUE;
3150     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
3151
3152     /* Handle recording of state blocks */
3153     if (This->isRecordingState) {
3154         TRACE("Recording... not performing anything\n");
3155         return WINED3D_OK;
3156     }
3157
3158     ENTER_GL();
3159     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3160         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3161     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3162         pMaterial->Ambient.b, pMaterial->Ambient.a);
3163     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3164         pMaterial->Specular.b, pMaterial->Specular.a);
3165     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3166         pMaterial->Emissive.b, pMaterial->Emissive.a);
3167     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3168
3169     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
3170     checkGLcall("glMaterialfv(GL_AMBIENT)");
3171     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
3172     checkGLcall("glMaterialfv(GL_DIFFUSE)");
3173
3174     /* Only change material color if specular is enabled, otherwise it is set to black */
3175     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
3176        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3177        checkGLcall("glMaterialfv(GL_SPECULAR");
3178     } else {
3179        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3180        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3181        checkGLcall("glMaterialfv(GL_SPECULAR");
3182     }
3183     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
3184     checkGLcall("glMaterialfv(GL_EMISSION)");
3185     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
3186     checkGLcall("glMaterialf(GL_SHININESS");
3187
3188     LEAVE_GL();
3189     return WINED3D_OK;
3190 }
3191
3192 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3193     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3194     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
3195     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3196         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3197     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3198         pMaterial->Ambient.b, pMaterial->Ambient.a);
3199     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3200         pMaterial->Specular.b, pMaterial->Specular.a);
3201     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3202         pMaterial->Emissive.b, pMaterial->Emissive.a);
3203     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3204
3205     return WINED3D_OK;
3206 }
3207
3208 /*****
3209  * Get / Set Indices
3210  *****/
3211 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
3212                                              UINT BaseVertexIndex) {
3213     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
3214     IWineD3DIndexBuffer *oldIdxs;
3215
3216     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3217     oldIdxs = This->updateStateBlock->pIndexData;
3218
3219     This->updateStateBlock->changed.indices = TRUE;
3220     This->updateStateBlock->set.indices = TRUE;
3221     This->updateStateBlock->pIndexData = pIndexData;
3222     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
3223
3224     /* Handle recording of state blocks */
3225     if (This->isRecordingState) {
3226         TRACE("Recording... not performing anything\n");
3227         return WINED3D_OK;
3228     }
3229
3230     if (NULL != pIndexData) {
3231         IWineD3DIndexBuffer_AddRef(pIndexData);
3232     }
3233     if (NULL != oldIdxs) {
3234         IWineD3DIndexBuffer_Release(oldIdxs);
3235     }
3236     return WINED3D_OK;
3237 }
3238
3239 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3240     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3241
3242     *ppIndexData = This->stateBlock->pIndexData;
3243
3244     /* up ref count on ppindexdata */
3245     if (*ppIndexData) {
3246         IWineD3DIndexBuffer_AddRef(*ppIndexData);
3247         *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3248         TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3249     }else{
3250         TRACE("(%p) No index data set\n", This);
3251     }
3252     TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3253
3254     return WINED3D_OK;
3255 }
3256
3257 /*****
3258  * Get / Set Viewports
3259  *****/
3260 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3261     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3262
3263     TRACE("(%p)\n", This);
3264     This->updateStateBlock->changed.viewport = TRUE;
3265     This->updateStateBlock->set.viewport = TRUE;
3266     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3267
3268     /* Handle recording of state blocks */
3269     if (This->isRecordingState) {
3270         TRACE("Recording... not performing anything\n");
3271         return WINED3D_OK;
3272     }
3273     This->viewport_changed = TRUE;
3274
3275     ENTER_GL();
3276
3277     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3278           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3279
3280     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
3281     checkGLcall("glDepthRange");
3282     /* Note: GL requires lower left, DirectX supplies upper left */
3283     /* TODO: replace usage of renderTarget with context management */
3284     glViewport(pViewport->X,
3285                (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
3286                pViewport->Width, pViewport->Height);
3287
3288     checkGLcall("glViewport");
3289
3290     LEAVE_GL();
3291
3292     return WINED3D_OK;
3293
3294 }
3295
3296 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3297     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3298     TRACE("(%p)\n", This);
3299     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3300     return WINED3D_OK;
3301 }
3302
3303 static void renderstate_stencil_twosided(
3304         IWineD3DDeviceImpl *This,
3305         GLint face,
3306         GLint func,
3307         GLint ref,
3308         GLuint mask,
3309         GLint stencilFail,
3310         GLint depthFail,
3311         GLint stencilPass ) {
3312 #if 0 /* Don't use OpenGL 2.0 calls for now */
3313             if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
3314                 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
3315                 checkGLcall("glStencilFuncSeparate(...)");
3316                 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
3317                 checkGLcall("glStencilOpSeparate(...)");
3318             }
3319             else
3320 #endif
3321             if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
3322                 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
3323                 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3324                 GL_EXTCALL(glActiveStencilFaceEXT(face));
3325                 checkGLcall("glActiveStencilFaceEXT(...)");
3326                 glStencilFunc(func, ref, mask);
3327                 checkGLcall("glStencilFunc(...)");
3328                 glStencilOp(stencilFail, depthFail, stencilPass);
3329                 checkGLcall("glStencilOp(...)");
3330             } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3331                 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
3332                 checkGLcall("glStencilFuncSeparateATI(...)");
3333                 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
3334                 checkGLcall("glStencilOpSeparateATI(...)");
3335             } else {
3336                 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
3337             }
3338 }
3339
3340 static void renderstate_stencil(IWineD3DDeviceImpl *This, D3DRENDERSTATETYPE State, DWORD Value) {
3341     DWORD onesided_enable = FALSE;
3342     DWORD twosided_enable = FALSE;
3343     GLint func = GL_ALWAYS;
3344     GLint func_ccw = GL_ALWAYS;
3345     GLint ref = 0;
3346     GLuint mask = 0;
3347     GLint stencilFail = GL_KEEP;
3348     GLint depthFail = GL_KEEP;
3349     GLint stencilPass = GL_KEEP;
3350     GLint stencilFail_ccw = GL_KEEP;
3351     GLint depthFail_ccw = GL_KEEP;
3352     GLint stencilPass_ccw = GL_KEEP;
3353
3354     if( This->stateBlock->set.renderState[WINED3DRS_STENCILENABLE] )
3355         onesided_enable = This->stateBlock->renderState[WINED3DRS_STENCILENABLE];
3356     if( This->stateBlock->set.renderState[WINED3DRS_TWOSIDEDSTENCILMODE] )
3357         twosided_enable = This->stateBlock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
3358     if( This->stateBlock->set.renderState[WINED3DRS_STENCILFUNC] )
3359         if( !( func = CompareFunc(This->stateBlock->renderState[WINED3DRS_STENCILFUNC]) ) )
3360             func = GL_ALWAYS;
3361     if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFUNC] )
3362         if( !( func_ccw = CompareFunc(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
3363             func = GL_ALWAYS;
3364     if( This->stateBlock->set.renderState[WINED3DRS_STENCILREF] )
3365         ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
3366     if( This->stateBlock->set.renderState[WINED3DRS_STENCILMASK] )
3367         mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
3368     if( This->stateBlock->set.renderState[WINED3DRS_STENCILFAIL] )
3369         stencilFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILFAIL]);
3370     if( This->stateBlock->set.renderState[WINED3DRS_STENCILZFAIL] )
3371         depthFail = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILZFAIL]);
3372     if( This->stateBlock->set.renderState[WINED3DRS_STENCILPASS] )
3373         stencilPass = StencilOp(This->stateBlock->renderState[WINED3DRS_STENCILPASS]);
3374     if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILFAIL] )
3375         stencilFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILFAIL]);
3376     if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILZFAIL] )
3377         depthFail_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
3378     if( This->stateBlock->set.renderState[WINED3DRS_CCW_STENCILPASS] )
3379         stencilPass_ccw = StencilOp(This->stateBlock->renderState[WINED3DRS_CCW_STENCILPASS]);
3380
3381     TRACE("(onesided %d, twosided %d, ref %x, mask %x,  \
3382         GL_FRONT: func: %x, fail %x, zfail %x, zpass %x  \
3383         GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
3384             onesided_enable, twosided_enable, ref, mask,
3385             func, stencilFail, depthFail, stencilPass,
3386             func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3387
3388     if (twosided_enable) {
3389         renderstate_stencil_twosided(This, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
3390         renderstate_stencil_twosided(This, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
3391     } else {
3392         if (onesided_enable) {
3393             glEnable(GL_STENCIL_TEST);
3394             checkGLcall("glEnable GL_STENCIL_TEST");
3395             glStencilFunc(func, ref, mask);
3396             checkGLcall("glStencilFunc(...)");
3397             glStencilOp(stencilFail, depthFail, stencilPass);
3398             checkGLcall("glStencilOp(...)");
3399         } else {
3400             glDisable(GL_STENCIL_TEST);
3401             checkGLcall("glDisable GL_STENCIL_TEST");
3402         }
3403     }
3404 }
3405
3406 /*****
3407  * Get / Set Render States
3408  * TODO: Verify against dx9 definitions
3409  *****/
3410 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
3411
3412     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
3413     DWORD                OldValue = This->stateBlock->renderState[State];
3414
3415     /* Simple way of referring to either a DWORD or a 4 byte float */
3416     union {
3417         DWORD d;
3418         float f;
3419     } tmpvalue;
3420
3421     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3422     This->updateStateBlock->changed.renderState[State] = TRUE;
3423     This->updateStateBlock->set.renderState[State] = TRUE;
3424     This->updateStateBlock->renderState[State] = Value;
3425
3426     /* Handle recording of state blocks */
3427     if (This->isRecordingState) {
3428         TRACE("Recording... not performing anything\n");
3429         return WINED3D_OK;
3430     }
3431
3432     ENTER_GL();
3433
3434     switch (State) {
3435     case WINED3DRS_FILLMODE                  :
3436         switch ((D3DFILLMODE) Value) {
3437         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
3438         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
3439         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
3440         default:
3441             FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
3442         }
3443         checkGLcall("glPolygonMode (fillmode)");
3444         break;
3445
3446     case WINED3DRS_LIGHTING                  :
3447         if (Value) {
3448             glEnable(GL_LIGHTING);
3449             checkGLcall("glEnable GL_LIGHTING");
3450         } else {
3451             glDisable(GL_LIGHTING);
3452             checkGLcall("glDisable GL_LIGHTING");
3453         }
3454         break;
3455
3456     case WINED3DRS_ZENABLE                   :
3457         switch ((D3DZBUFFERTYPE) Value) {
3458         case D3DZB_FALSE:
3459             glDisable(GL_DEPTH_TEST);
3460             checkGLcall("glDisable GL_DEPTH_TEST");
3461             break;
3462         case D3DZB_TRUE:
3463             glEnable(GL_DEPTH_TEST);
3464             checkGLcall("glEnable GL_DEPTH_TEST");
3465             break;
3466         case D3DZB_USEW:
3467             glEnable(GL_DEPTH_TEST);
3468             checkGLcall("glEnable GL_DEPTH_TEST");
3469             FIXME("W buffer is not well handled\n");
3470             break;
3471         default:
3472             FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", Value);
3473         }
3474         break;
3475
3476     case WINED3DRS_CULLMODE                  :
3477
3478         /* If we are culling "back faces with clockwise vertices" then
3479            set front faces to be counter clockwise and enable culling
3480            of back faces                                               */
3481         switch ((D3DCULL) Value) {
3482         case D3DCULL_NONE:
3483             glDisable(GL_CULL_FACE);
3484             checkGLcall("glDisable GL_CULL_FACE");
3485             break;
3486         case D3DCULL_CW:
3487             glEnable(GL_CULL_FACE);
3488             checkGLcall("glEnable GL_CULL_FACE");
3489             if (This->renderUpsideDown) {
3490                 glFrontFace(GL_CW);
3491                 checkGLcall("glFrontFace GL_CW");
3492             } else {
3493                 glFrontFace(GL_CCW);
3494                 checkGLcall("glFrontFace GL_CCW");
3495             }
3496             glCullFace(GL_BACK);
3497             break;
3498         case D3DCULL_CCW:
3499             glEnable(GL_CULL_FACE);
3500             checkGLcall("glEnable GL_CULL_FACE");
3501             if (This->renderUpsideDown) {
3502                 glFrontFace(GL_CCW);
3503                 checkGLcall("glFrontFace GL_CCW");
3504             } else {
3505                 glFrontFace(GL_CW);
3506                 checkGLcall("glFrontFace GL_CW");
3507             }
3508             glCullFace(GL_BACK);
3509             break;
3510         default:
3511             FIXME("Unrecognized/Unhandled D3DCULL value %d\n", Value);
3512         }
3513         break;
3514
3515     case WINED3DRS_SHADEMODE                 :
3516         switch ((D3DSHADEMODE) Value) {
3517         case D3DSHADE_FLAT:
3518             glShadeModel(GL_FLAT);
3519             checkGLcall("glShadeModel");
3520             break;
3521         case D3DSHADE_GOURAUD:
3522             glShadeModel(GL_SMOOTH);
3523             checkGLcall("glShadeModel");
3524             break;
3525         case D3DSHADE_PHONG:
3526             FIXME("D3DSHADE_PHONG isn't supported\n");
3527             break;
3528         default:
3529             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %d\n", Value);
3530         }
3531         break;
3532
3533     case WINED3DRS_DITHERENABLE              :
3534         if (Value) {
3535             glEnable(GL_DITHER);
3536             checkGLcall("glEnable GL_DITHER");
3537         } else {
3538             glDisable(GL_DITHER);
3539             checkGLcall("glDisable GL_DITHER");
3540         }
3541         break;
3542
3543     case WINED3DRS_ZWRITEENABLE              :
3544         if (Value) {
3545             glDepthMask(1);
3546             checkGLcall("glDepthMask");
3547         } else {
3548             glDepthMask(0);
3549             checkGLcall("glDepthMask");
3550         }
3551         break;
3552
3553     case WINED3DRS_ZFUNC                     :
3554         {
3555             int glParm = CompareFunc(Value);
3556
3557             if(glParm) {
3558                 glDepthFunc(glParm);
3559                 checkGLcall("glDepthFunc");
3560             }
3561         }
3562         break;
3563
3564     case WINED3DRS_AMBIENT                   :
3565         {
3566             float col[4];
3567             D3DCOLORTOGLFLOAT4(Value, col);
3568             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
3569             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
3570             checkGLcall("glLightModel for MODEL_AMBIENT");
3571
3572         }
3573         break;
3574
3575     case WINED3DRS_ALPHABLENDENABLE          :
3576         if (Value) {
3577             glEnable(GL_BLEND);
3578             checkGLcall("glEnable GL_BLEND");
3579         } else {
3580             glDisable(GL_BLEND);
3581             checkGLcall("glDisable GL_BLEND");
3582         };
3583         break;
3584
3585     case WINED3DRS_SRCBLEND                  :
3586     case WINED3DRS_DESTBLEND                 :
3587         {
3588             int newVal = GL_ZERO;
3589             switch (Value) {
3590             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
3591             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
3592             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
3593             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
3594             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
3595             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
3596             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
3597             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
3598             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
3599             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
3600             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
3601
3602             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
3603                 This->srcBlend = newVal;
3604                 This->dstBlend = newVal;
3605                 break;
3606
3607             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
3608                 This->srcBlend = newVal;
3609                 This->dstBlend = newVal;
3610                 break;
3611             case D3DBLEND_BLENDFACTOR        : newVal = GL_CONSTANT_COLOR;   break;
3612             case D3DBLEND_INVBLENDFACTOR     : newVal = GL_ONE_MINUS_CONSTANT_COLOR;  break;
3613             default:
3614                 FIXME("Unrecognized src/dest blend value %d (%d)\n", Value, State);
3615             }
3616
3617             if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
3618             if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
3619             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
3620             glBlendFunc(This->srcBlend, This->dstBlend);
3621
3622             checkGLcall("glBlendFunc");
3623         }
3624         break;
3625
3626     case WINED3DRS_ALPHATESTENABLE           :
3627     case WINED3DRS_ALPHAFUNC                 :
3628     case WINED3DRS_ALPHAREF                  :
3629     case WINED3DRS_COLORKEYENABLE            :
3630         {
3631             int glParm = 0;
3632             float ref;
3633             BOOL enable_ckey = FALSE;
3634
3635             IWineD3DSurfaceImpl *surf;
3636
3637             /* Find out if the texture on the first stage has a ckey set */
3638             if(This->stateBlock->textures[0]) {
3639                 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[0])->surfaces[0];
3640                 if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
3641             }
3642
3643             if (This->stateBlock->renderState[WINED3DRS_ALPHATESTENABLE] ||
3644                 (This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
3645                 glEnable(GL_ALPHA_TEST);
3646                 checkGLcall("glEnable GL_ALPHA_TEST");
3647             } else {
3648                 glDisable(GL_ALPHA_TEST);
3649                 checkGLcall("glDisable GL_ALPHA_TEST");
3650                 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3651                  * enable call
3652                  */
3653                  break;
3654             }
3655
3656             if(This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
3657                 glParm = GL_NOTEQUAL;
3658                 ref = 0.0;
3659             } else {
3660                 ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
3661                 glParm = CompareFunc(This->stateBlock->renderState[WINED3DRS_ALPHAFUNC]);
3662             }
3663             if(glParm) {
3664                 This->alphafunc = glParm;
3665                 glAlphaFunc(glParm, ref);
3666                 checkGLcall("glAlphaFunc");
3667             }
3668         }
3669         break;
3670
3671     case WINED3DRS_CLIPPLANEENABLE           :
3672     case WINED3DRS_CLIPPING                  :
3673         {
3674             /* Ensure we only do the changed clip planes */
3675             DWORD enable  = 0xFFFFFFFF;
3676             DWORD disable = 0x00000000;
3677
3678             /* If enabling / disabling all */
3679             if (State == WINED3DRS_CLIPPING) {
3680                 if (Value) {
3681                     enable  = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3682                     disable = 0x00;
3683                 } else {
3684                     disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
3685                     enable  = 0x00;
3686                 }
3687             } else {
3688                 enable =   Value & ~OldValue;
3689                 disable = ~Value &  OldValue;
3690             }
3691
3692             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
3693             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
3694             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
3695             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
3696             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
3697             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
3698
3699             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3700             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3701             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3702             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3703             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3704             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3705
3706             /** update clipping status */
3707             if (enable) {
3708               This->stateBlock->clip_status.ClipUnion = 0;
3709               This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
3710             } else {
3711               This->stateBlock->clip_status.ClipUnion = 0;
3712               This->stateBlock->clip_status.ClipIntersection = 0;
3713             }
3714         }
3715         break;
3716
3717     case WINED3DRS_BLENDOP                   :
3718         {
3719             int glParm = GL_FUNC_ADD;
3720
3721             switch ((D3DBLENDOP) Value) {
3722             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
3723             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
3724             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3725             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
3726             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
3727             default:
3728                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", Value);
3729             }
3730
3731             if(GL_SUPPORT(EXT_BLEND_MINMAX)) {
3732                 TRACE("glBlendEquation(%x)\n", glParm);
3733                 GL_EXTCALL(glBlendEquation(glParm));
3734                 checkGLcall("glBlendEquation");
3735             } else {
3736                 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3737             }
3738         }
3739         break;
3740
3741     case WINED3DRS_TEXTUREFACTOR             :
3742         {
3743             unsigned int i;
3744
3745             /* Note the texture color applies to all textures whereas
3746                GL_TEXTURE_ENV_COLOR applies to active only */
3747             float col[4];
3748             D3DCOLORTOGLFLOAT4(Value, col);
3749
3750             if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3751                 /* And now the default texture color as well */
3752                 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
3753                     /* Note the D3DRS value applies to all textures, but GL has one
3754                        per texture, so apply it now ready to be used!               */
3755                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3756                         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
3757                         checkGLcall("glActiveTextureARB");
3758                     } else if (i>0) {
3759                         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3760                     }
3761
3762                     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3763                     checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3764                 }
3765             }
3766         }
3767         break;
3768
3769     case WINED3DRS_SPECULARENABLE            :
3770         {
3771             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3772                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3773                specular color. This is wrong:
3774                Separate specular color means the specular colour is maintained separately, whereas
3775                single color means it is merged in. However in both cases they are being used to
3776                some extent.
3777                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3778                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3779                   running 1.4 yet!
3780              */
3781             /*
3782              * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
3783              * Instead, we need to setup the FinalCombiner properly.
3784              *
3785              * The default setup for the FinalCombiner is:
3786              *
3787              * <variable>       <input>                             <mapping>               <usage>
3788              * GL_VARIABLE_A_NV GL_FOG,                             GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3789              * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV   GL_UNSIGNED_IDENTITY_NV GL_RGB
3790              * GL_VARIABLE_C_NV GL_FOG                              GL_UNSIGNED_IDENTITY_NV GL_RGB
3791              * GL_VARIABLE_D_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
3792              * GL_VARIABLE_E_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
3793              * GL_VARIABLE_F_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
3794              * GL_VARIABLE_G_NV GL_SPARE0_NV                        GL_UNSIGNED_IDENTITY_NV GL_ALPHA
3795              *
3796              * That's pretty much fine as it is, except for variable B, which needs to take
3797              * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
3798              * whether WINED3DRS_SPECULARENABLE is enabled or not.
3799              */
3800
3801               if (Value) {
3802                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
3803                 checkGLcall("glMaterialfv");
3804                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3805                   glEnable(GL_COLOR_SUM_EXT);
3806                 } else {
3807                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
3808                 }
3809                 checkGLcall("glEnable(GL_COLOR_SUM)");
3810
3811                 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3812                     GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3813                     checkGLcall("glFinalCombinerInputNV()");
3814                 }
3815               } else {
3816                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3817
3818                 /* for the case of enabled lighting: */
3819                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3820                 checkGLcall("glMaterialfv");
3821
3822                 /* for the case of disabled lighting: */
3823                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3824                   glDisable(GL_COLOR_SUM_EXT);
3825                 } else {
3826                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
3827                 }
3828                 checkGLcall("glDisable(GL_COLOR_SUM)");
3829
3830                 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3831                     GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
3832                     checkGLcall("glFinalCombinerInputNV()");
3833                 }
3834               }
3835         }
3836         break;
3837
3838     case WINED3DRS_STENCILENABLE :
3839     case WINED3DRS_TWOSIDEDSTENCILMODE :
3840     case WINED3DRS_STENCILFUNC :
3841     case WINED3DRS_CCW_STENCILFUNC :
3842     case WINED3DRS_STENCILREF :
3843     case WINED3DRS_STENCILMASK :
3844     case WINED3DRS_STENCILFAIL :
3845     case WINED3DRS_STENCILZFAIL :
3846     case WINED3DRS_STENCILPASS :
3847     case WINED3DRS_CCW_STENCILFAIL :
3848     case WINED3DRS_CCW_STENCILZFAIL :
3849     case WINED3DRS_CCW_STENCILPASS :
3850         renderstate_stencil(This, State, Value);
3851         break;
3852     case WINED3DRS_STENCILWRITEMASK          :
3853         {
3854             glStencilMask(Value);
3855             TRACE("glStencilMask(%u)\n", Value);
3856             checkGLcall("glStencilMask");
3857         }
3858         break;
3859
3860     case WINED3DRS_FOGENABLE                 :
3861         {
3862           if (Value) {
3863                glEnable(GL_FOG);
3864                checkGLcall("glEnable GL_FOG");
3865             } else {
3866                glDisable(GL_FOG);
3867                checkGLcall("glDisable GL_FOG");
3868             }
3869         }
3870         break;
3871
3872     case WINED3DRS_RANGEFOGENABLE            :
3873         {
3874             if (Value) {
3875               TRACE("Enabled RANGEFOG\n");
3876             } else {
3877               TRACE("Disabled RANGEFOG\n");
3878             }
3879         }
3880         break;
3881
3882     case WINED3DRS_FOGCOLOR                  :
3883         {
3884             float col[4];
3885             D3DCOLORTOGLFLOAT4(Value, col);
3886             /* Set the default alpha blend color */
3887             glFogfv(GL_FOG_COLOR, &col[0]);
3888             checkGLcall("glFog GL_FOG_COLOR");
3889         }
3890         break;
3891
3892     case WINED3DRS_FOGTABLEMODE              :
3893     case WINED3DRS_FOGVERTEXMODE             :
3894         {
3895           /* 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." */
3896           if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
3897               glHint(GL_FOG_HINT, GL_FASTEST);
3898               checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
3899               switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
3900                   /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
3901                    * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
3902                    */
3903                   case D3DFOG_EXP:  {
3904                       if(!This->last_was_rhw) {
3905                           glFogi(GL_FOG_MODE, GL_EXP);
3906                           checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3907                           if(GL_SUPPORT(EXT_FOG_COORD)) {
3908                               glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3909                               checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3910                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3911                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3912                           }
3913                           break;
3914                       }
3915                   }
3916                   case D3DFOG_EXP2: {
3917                       if(!This->last_was_rhw) {
3918                           glFogi(GL_FOG_MODE, GL_EXP2);
3919                           checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3920                           if(GL_SUPPORT(EXT_FOG_COORD)) {
3921                               glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3922                               checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3923                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3924                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3925                           }
3926                           break;
3927                       }
3928                   }
3929                   case D3DFOG_LINEAR: {
3930                       if(!This->last_was_rhw) {
3931                           glFogi(GL_FOG_MODE, GL_LINEAR);
3932                           checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3933                           if(GL_SUPPORT(EXT_FOG_COORD)) {
3934                               glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3935                               checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3936                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3937                               IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3938                           }
3939                           break;
3940                       }
3941                   }
3942                   case D3DFOG_NONE: {
3943                       /* Both are none? According to msdn the alpha channel of the specular
3944                        * color contains a fog factor. Set it in drawStridedSlow.
3945                        * Same happens with Vertexfog on transformed vertices
3946                        */
3947                       if(GL_SUPPORT(EXT_FOG_COORD)) {
3948                           glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
3949                           checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
3950                           glFogi(GL_FOG_MODE, GL_LINEAR);
3951                           checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
3952                           glFogf(GL_FOG_START, (float) 0xff);
3953                           checkGLcall("glFogfv GL_FOG_START");
3954                           glFogf(GL_FOG_END, 0.0);
3955                           checkGLcall("glFogfv GL_FOG_END");
3956                       } else {
3957                           /* Disable GL fog, handle this in software in drawStridedSlow */
3958                           glDisable(GL_FOG);
3959                           checkGLcall("glDisable(GL_FOG)");
3960                       }
3961                   break;
3962                   }
3963                   default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
3964               }
3965           } else {
3966               glHint(GL_FOG_HINT, GL_NICEST);
3967               checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
3968               switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
3969                   case D3DFOG_EXP:    glFogi(GL_FOG_MODE, GL_EXP);
3970                                       checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
3971                                       if(GL_SUPPORT(EXT_FOG_COORD)) {
3972                                           glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3973                                           checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3974                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3975                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3976                                       }
3977                                       break;
3978                   case D3DFOG_EXP2:   glFogi(GL_FOG_MODE, GL_EXP2);
3979                                       checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
3980                                       if(GL_SUPPORT(EXT_FOG_COORD)) {
3981                                           glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3982                                           checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3983                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3984                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3985                                       }
3986                                       break;
3987                   case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR);
3988                                       checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3989                                       if(GL_SUPPORT(EXT_FOG_COORD)) {
3990                                           glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
3991                                           checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
3992                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
3993                                           IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
3994                                       }
3995                                       break;
3996                   case D3DFOG_NONE:   /* Won't happen */
3997                   default:            FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
3998               }
3999           }
4000           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
4001             glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
4002           }
4003         }
4004         break;
4005
4006     case WINED3DRS_FOGSTART                  :
4007         {
4008             tmpvalue.d = Value;
4009             glFogfv(GL_FOG_START, &tmpvalue.f);
4010             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
4011             TRACE("Fog Start == %f\n", tmpvalue.f);
4012         }
4013         break;
4014
4015     case WINED3DRS_FOGEND                    :
4016         {
4017             tmpvalue.d = Value;
4018             glFogfv(GL_FOG_END, &tmpvalue.f);
4019             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
4020             TRACE("Fog End == %f\n", tmpvalue.f);
4021         }
4022         break;
4023
4024     case WINED3DRS_FOGDENSITY                :
4025         {
4026             tmpvalue.d = Value;
4027             glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
4028             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
4029         }
4030         break;
4031
4032     case WINED3DRS_VERTEXBLEND               :
4033         {
4034           This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
4035           TRACE("Vertex Blending state to %d\n",  Value);
4036         }
4037         break;
4038
4039     case WINED3DRS_TWEENFACTOR               :
4040         {
4041           tmpvalue.d = Value;
4042           This->updateStateBlock->tween_factor = tmpvalue.f;
4043           TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
4044         }
4045         break;
4046
4047     case WINED3DRS_INDEXEDVERTEXBLENDENABLE  :
4048         {
4049           TRACE("Indexed Vertex Blend Enable to %u\n", (BOOL) Value);
4050         }
4051         break;
4052
4053     case WINED3DRS_COLORVERTEX               :
4054     case WINED3DRS_DIFFUSEMATERIALSOURCE     :
4055     case WINED3DRS_SPECULARMATERIALSOURCE    :
4056     case WINED3DRS_AMBIENTMATERIALSOURCE     :
4057     case WINED3DRS_EMISSIVEMATERIALSOURCE    :
4058         {
4059             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
4060
4061             if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
4062                 TRACE("diff %d, amb %d, emis %d, spec %d\n",
4063                       This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
4064                       This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
4065                       This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
4066                       This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
4067
4068                 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
4069                     if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4070                         Parm = GL_AMBIENT_AND_DIFFUSE;
4071                     } else {
4072                         Parm = GL_DIFFUSE;
4073                     }
4074                 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
4075                     Parm = GL_AMBIENT;
4076                 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
4077                     Parm = GL_EMISSION;
4078                 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
4079                     Parm = GL_SPECULAR;
4080                 } else {
4081                     Parm = -1;
4082                 }
4083
4084                 if (Parm == -1) {
4085                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4086                 } else {
4087                     This->tracking_color = NEEDS_TRACKING;
4088                     This->tracking_parm  = Parm;
4089                 }
4090
4091             } else {
4092                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
4093             }
4094         }
4095         break;
4096
4097     case WINED3DRS_LINEPATTERN               :
4098         {
4099             union {
4100                 DWORD                 d;
4101                 D3DLINEPATTERN        lp;
4102             } tmppattern;
4103             tmppattern.d = Value;
4104
4105             TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4106
4107             if (tmppattern.lp.wRepeatFactor) {
4108                 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
4109                 checkGLcall("glLineStipple(repeat, linepattern)");
4110                 glEnable(GL_LINE_STIPPLE);
4111                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
4112             } else {
4113                 glDisable(GL_LINE_STIPPLE);
4114                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
4115             }
4116         }
4117         break;
4118
4119     case WINED3DRS_ZBIAS                     : /* D3D8 only */
4120         {
4121             if (Value) {
4122                 tmpvalue.d = Value;
4123                 TRACE("ZBias value %f\n", tmpvalue.f);
4124                 glPolygonOffset(0, -tmpvalue.f);
4125                 checkGLcall("glPolygonOffset(0, -Value)");
4126                 glEnable(GL_POLYGON_OFFSET_FILL);
4127                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
4128                 glEnable(GL_POLYGON_OFFSET_LINE);
4129                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
4130                 glEnable(GL_POLYGON_OFFSET_POINT);
4131                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
4132             } else {
4133                 glDisable(GL_POLYGON_OFFSET_FILL);
4134                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
4135                 glDisable(GL_POLYGON_OFFSET_LINE);
4136                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
4137                 glDisable(GL_POLYGON_OFFSET_POINT);
4138                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
4139             }
4140         }
4141         break;
4142
4143     case WINED3DRS_NORMALIZENORMALS          :
4144         if (Value) {
4145             glEnable(GL_NORMALIZE);
4146             checkGLcall("glEnable(GL_NORMALIZE);");
4147         } else {
4148             glDisable(GL_NORMALIZE);
4149             checkGLcall("glDisable(GL_NORMALIZE);");
4150         }
4151         break;
4152
4153     case WINED3DRS_POINTSIZE                 :
4154         /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
4155         tmpvalue.d = Value;
4156         TRACE("Set point size to %f\n", tmpvalue.f);
4157         glPointSize(tmpvalue.f);
4158         checkGLcall("glPointSize(...);");
4159         break;
4160
4161     case WINED3DRS_POINTSIZE_MIN             :
4162         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4163           tmpvalue.d = Value;
4164           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
4165           checkGLcall("glPointParameterfEXT(...);");
4166         } else {
4167           FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
4168         }
4169         break;
4170
4171     case WINED3DRS_POINTSIZE_MAX             :
4172         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4173           tmpvalue.d = Value;
4174           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
4175           checkGLcall("glPointParameterfEXT(...);");
4176         } else {
4177           FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
4178         }
4179         break;
4180
4181     case WINED3DRS_POINTSCALE_A              :
4182     case WINED3DRS_POINTSCALE_B              :
4183     case WINED3DRS_POINTSCALE_C              :
4184     case WINED3DRS_POINTSCALEENABLE          :
4185     {
4186         /*
4187          * POINTSCALEENABLE controls how point size value is treated. If set to
4188          * true, the point size is scaled with respect to height of viewport.
4189          * When set to false point size is in pixels.
4190          *
4191          * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
4192          */
4193
4194         /* Default values */
4195         GLfloat att[3] = {1.0f, 0.0f, 0.0f};
4196
4197         /*
4198          * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
4199          * This means that OpenGL will clamp really small point sizes to 1.0f.
4200          * To correct for this we need to multiply by the scale factor when sizes
4201          * are less than 1.0f. scale_factor =  1.0f / point_size.
4202          */
4203         GLfloat pointSize = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSIZE]);
4204         if(pointSize > 0.0f) {
4205             GLfloat scaleFactor;
4206
4207             if(pointSize < 1.0f) {
4208                 scaleFactor = pointSize * pointSize;
4209             } else {
4210                 scaleFactor = 1.0f;
4211             }
4212
4213             if(This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
4214                 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]) /
4215                     (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4216                 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]) /
4217                     (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4218                 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]) /
4219                     (This->stateBlock->viewport.Height * This->stateBlock->viewport.Height * scaleFactor);
4220             }
4221         }
4222
4223         if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
4224             GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
4225             checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
4226         }
4227         else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
4228             GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
4229             checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
4230         } else {
4231             TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
4232         }
4233         break;
4234     }
4235     case WINED3DRS_COLORWRITEENABLE          :
4236       {
4237         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
4238               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
4239               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
4240               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
4241               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
4242         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE,
4243                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4244                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4245                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4246         checkGLcall("glColorMask(...)");
4247       }
4248       break;
4249
4250     case WINED3DRS_LOCALVIEWER               :
4251       {
4252         GLint state = (Value) ? 1 : 0;
4253         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
4254         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
4255       }
4256       break;
4257
4258     case WINED3DRS_LASTPIXEL                 :
4259       {
4260         if (Value) {
4261           TRACE("Last Pixel Drawing Enabled\n");
4262         } else {
4263           FIXME("Last Pixel Drawing Disabled, not handled yet\n");
4264         }
4265       }
4266       break;
4267
4268     case WINED3DRS_SOFTWAREVERTEXPROCESSING  :
4269       {
4270         if (Value) {
4271           TRACE("Software Processing Enabled\n");
4272         } else {
4273           TRACE("Software Processing Disabled\n");
4274         }
4275       }
4276       break;
4277
4278       /** not supported */
4279     case WINED3DRS_ZVISIBLE                  :
4280       {
4281         LEAVE_GL();
4282         return WINED3DERR_INVALIDCALL;
4283       }
4284     case WINED3DRS_POINTSPRITEENABLE         :
4285     {
4286         /* TODO: NV_POINT_SPRITE */
4287         if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
4288             TRACE("Point sprites not supported\n");
4289             break;
4290         }
4291
4292         /*
4293          * Point sprites are always enabled. Value controls texture coordinate
4294          * replacement mode. Must be set true for point sprites to use
4295          * textures.
4296          */
4297         glEnable(GL_POINT_SPRITE_ARB);
4298         checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
4299
4300         if (Value) {
4301             glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
4302             checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
4303         } else {
4304             glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
4305             checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
4306         }
4307         break;
4308     }
4309     case WINED3DRS_EDGEANTIALIAS             :
4310     {
4311         if(Value) {
4312             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4313             glEnable(GL_BLEND);
4314             checkGLcall("glEnable(GL_BLEND)");
4315             glEnable(GL_LINE_SMOOTH);
4316             checkGLcall("glEnable(GL_LINE_SMOOTH)");
4317         } else {
4318             if(!This->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
4319                 glDisable(GL_BLEND);
4320                 checkGLcall("glDisable(GL_BLEND)");
4321             }
4322             glDisable(GL_LINE_SMOOTH);
4323             checkGLcall("glDisable(GL_LINE_SMOOTH)");
4324         }
4325         break;
4326     }
4327     case WINED3DRS_WRAP0                     :
4328     case WINED3DRS_WRAP1                     :
4329     case WINED3DRS_WRAP2                     :
4330     case WINED3DRS_WRAP3                     :
4331     case WINED3DRS_WRAP4                     :
4332     case WINED3DRS_WRAP5                     :
4333     case WINED3DRS_WRAP6                     :
4334     case WINED3DRS_WRAP7                     :
4335     case WINED3DRS_WRAP8                     :
4336     case WINED3DRS_WRAP9                     :
4337     case WINED3DRS_WRAP10                    :
4338     case WINED3DRS_WRAP11                    :
4339     case WINED3DRS_WRAP12                    :
4340     case WINED3DRS_WRAP13                    :
4341     case WINED3DRS_WRAP14                    :
4342     case WINED3DRS_WRAP15                    :
4343     /**
4344     http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
4345     http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
4346     http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
4347     Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
4348     http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
4349
4350     so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
4351     */
4352     {
4353         if(Value) {
4354             ERR("(%p)->(%s,%d) Texture wraping not yet supported\n",This, debug_d3drenderstate(State), Value);
4355         }
4356         break;
4357     }
4358
4359     case WINED3DRS_MULTISAMPLEANTIALIAS      :
4360     {
4361         if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
4362             if(Value) {
4363                 glEnable(GL_MULTISAMPLE_ARB);
4364                 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
4365             } else {
4366                 glDisable(GL_MULTISAMPLE_ARB);
4367                 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
4368             }
4369         } else {
4370             if(Value) {
4371                 ERR("Multisample antialiasing not supported by gl\n");
4372             }
4373         }
4374         break;
4375     }
4376
4377     case WINED3DRS_SCISSORTESTENABLE :
4378     {
4379         if(Value) {
4380             glEnable(GL_SCISSOR_TEST);
4381             checkGLcall("glEnable(GL_SCISSOR_TEST)");
4382         } else {
4383             glDisable(GL_SCISSOR_TEST);
4384             checkGLcall("glDisable(GL_SCISSOR_TEST)");
4385         }
4386         break;
4387     }
4388     case WINED3DRS_SLOPESCALEDEPTHBIAS :
4389     {
4390         if(Value) {
4391             tmpvalue.d = Value;
4392             glEnable(GL_POLYGON_OFFSET_FILL);
4393             checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4394             glPolygonOffset(tmpvalue.f, *((float*)&This->stateBlock->renderState[WINED3DRS_DEPTHBIAS]));
4395             checkGLcall("glPolygonOffset(...)");
4396         } else {
4397             glDisable(GL_POLYGON_OFFSET_FILL);
4398             checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4399         }
4400         break;
4401     }
4402     case WINED3DRS_ANTIALIASEDLINEENABLE :
4403     {
4404         if(Value) {
4405             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4406             glEnable(GL_BLEND);
4407             checkGLcall("glEnable(GL_BLEND)");
4408             glEnable(GL_LINE_SMOOTH);
4409             checkGLcall("glEnable(GL_LINE_SMOOTH)");
4410         } else {
4411             glDisable(GL_BLEND);
4412             checkGLcall("glDisable(GL_BLEND)");
4413             glDisable(GL_LINE_SMOOTH);
4414             checkGLcall("glDisable(GL_LINE_SMOOTH)");
4415         }
4416         break;
4417     }
4418     case WINED3DRS_DEPTHBIAS :
4419     {
4420         if(Value) {
4421             tmpvalue.d = Value;
4422             glEnable(GL_POLYGON_OFFSET_FILL);
4423             checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4424             glPolygonOffset(*((float*)&This->stateBlock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS]), tmpvalue.f);
4425             checkGLcall("glPolygonOffset(...)");
4426         } else {
4427             glDisable(GL_POLYGON_OFFSET_FILL);
4428             checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4429         }
4430         break;
4431     }
4432
4433     case WINED3DRS_TEXTUREPERSPECTIVE    :
4434     {
4435         if (Value)
4436             glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
4437         else
4438             glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4439         break;
4440     }
4441
4442     case WINED3DRS_STIPPLEDALPHA    :
4443     {
4444         if (Value)
4445             ERR(" Stippled Alpha not supported yet.\n");
4446         break;
4447     }
4448     case WINED3DRS_ANTIALIAS :
4449     {
4450         if (Value)
4451             ERR(" Antialias not supported yet.\n");
4452         break;
4453     }
4454
4455     case WINED3DRS_MULTISAMPLEMASK :
4456     {
4457         if(0xFFFFFFFF != Value)
4458             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4459         break;
4460     }
4461
4462     case WINED3DRS_PATCHEDGESTYLE :
4463     {
4464         if(D3DPATCHEDGE_DISCRETE != Value)
4465             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4466         break;
4467     }
4468
4469     case WINED3DRS_PATCHSEGMENTS :
4470     {
4471         /* available in d3d8 but in d3d9 it was replaced by IDirect3DDevice9::SetNPatchMode */
4472         tmpvalue.f = 1.0f;
4473         if(tmpvalue.d != Value)
4474             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4475         break;
4476     }
4477
4478     case WINED3DRS_DEBUGMONITORTOKEN :
4479     {
4480         /* Only useful for "debug builds". */
4481         if(0xbaadcafe != Value) {
4482             /* MSDN says the default is D3DDMT_ENABLE but our tests confirm 0xbaadcafe is the default. */
4483             /* MSDN says anything other than D3DDMT_ENABLE or DISABLE does not change the state,
4484              * but our tests disagree.
4485              * We do not claim to implement a debugging lib, so do not write an ERR
4486              */
4487             WARN("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4488         }
4489         break;
4490     }
4491
4492     case WINED3DRS_POSITIONDEGREE :
4493     {
4494         if(D3DDEGREE_CUBIC != Value)
4495             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4496         break;
4497     }
4498
4499     case WINED3DRS_NORMALDEGREE :
4500     {
4501         if(D3DDEGREE_LINEAR != Value)
4502             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4503         break;
4504     }
4505
4506     case WINED3DRS_MINTESSELLATIONLEVEL :
4507     case WINED3DRS_MAXTESSELLATIONLEVEL :
4508     case WINED3DRS_ADAPTIVETESS_X :
4509     case WINED3DRS_ADAPTIVETESS_Y :
4510     case WINED3DRS_ADAPTIVETESS_Z :
4511     case WINED3DRS_ADAPTIVETESS_W :
4512     {
4513         if(This->stateBlock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
4514             FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4515         else
4516             TRACE("(%p)->(%s,%d): recording state but WINED3DRS_ENABLEADAPTIVETESSELLATION is not enabled\n", This, debug_d3drenderstate(State), Value);
4517         break;
4518     }
4519
4520     case WINED3DRS_ENABLEADAPTIVETESSELLATION:
4521     {
4522         if(Value)
4523             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4524         break;
4525     }
4526
4527     case WINED3DRS_COLORWRITEENABLE1         :
4528     case WINED3DRS_COLORWRITEENABLE2         :
4529     case WINED3DRS_COLORWRITEENABLE3         :
4530     {
4531         /* depends on WINED3DRS_COLORWRITEENABLE. */
4532         if(0x0000000F != Value)
4533             ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4534         break;
4535     }
4536
4537     case WINED3DRS_BLENDFACTOR               :
4538     {
4539         float col[4];
4540
4541         TRACE("Setting BlendFactor to %d\n", Value);
4542
4543         D3DCOLORTOGLFLOAT4(Value, col);
4544         if (0xFFFFFFFF != Value) {
4545             glEnable(GL_BLEND);
4546             checkGLcall("glEnable(GL_BLEND)");
4547         }
4548         else {
4549            glDisable(GL_BLEND);
4550            checkGLcall("glDisable(GL_BLEND)");
4551         }
4552         glBlendColor (col[0],col[1],col[2],col[3]);
4553         break;
4554     }
4555
4556     case WINED3DRS_SRGBWRITEENABLE           :
4557     {
4558         if(Value)
4559             ERR("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4560         break;
4561     }
4562
4563     case WINED3DRS_SEPARATEALPHABLENDENABLE  :
4564     {
4565         if(Value)
4566             ERR("(%p)->(%s,%d) not yet implemented. Missing of cap D3DPMISCCAPS_SEPARATEALPHABLEND wasn't honored?\n", This, debug_d3drenderstate(State), Value);
4567         break;
4568     }
4569
4570     case WINED3DRS_SRCBLENDALPHA             :
4571     case WINED3DRS_DESTBLENDALPHA            :
4572     case WINED3DRS_BLENDOPALPHA              :
4573     {
4574         if(This->stateBlock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
4575             FIXME("(%p)->(%s,%d) not yet implemented\n", This, debug_d3drenderstate(State), Value);
4576         else
4577             TRACE("(%p)->(%s,%d): recording state but WINED3DRS_SEPARATEALPHABLENDENABLE is not enabled\n", This, debug_d3drenderstate(State), Value);
4578         break;
4579     }
4580
4581     default:
4582         FIXME("(%p)->(%s,%d) unknown state\n", This, debug_d3drenderstate(State), Value);
4583     }
4584
4585     LEAVE_GL();
4586
4587     return WINED3D_OK;
4588 }
4589
4590 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
4591     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4592     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
4593     *pValue = This->stateBlock->renderState[State];
4594     return WINED3D_OK;
4595 }
4596
4597 /*****
4598  * Get / Set Sampler States
4599  * TODO: Verify against dx9 definitions
4600  *****/
4601
4602 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
4603     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4604     /**
4605     * SetSampler is designed to allow for more than the standard up to 8 textures
4606     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
4607     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4608     *
4609     * http://developer.nvidia.com/object/General_FAQ.html#t6
4610     *
4611     * There are two new settings for GForce
4612     * the sampler one:
4613     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4614     * and the texture one:
4615     * GL_MAX_TEXTURE_COORDS_ARB.
4616     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4617      ******************/
4618     /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4619     if(Sampler >  GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
4620          FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
4621             Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
4622         return WINED3DERR_INVALIDCALL;
4623     }
4624
4625     TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
4626         debug_d3dsamplerstate(Type), Type, Value);
4627     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
4628     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
4629     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
4630
4631     /* Handle recording of state blocks */
4632     if (This->isRecordingState) {
4633         TRACE("Recording... not performing anything\n");
4634         return WINED3D_OK;
4635     }
4636
4637     return WINED3D_OK;
4638 }
4639
4640 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
4641     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4642     /** TODO: check that sampler is in  range **/
4643     *Value = This->updateStateBlock->samplerState[Sampler][Type];
4644     TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
4645
4646     return WINED3D_OK;
4647 }
4648
4649 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
4650     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4651     ENTER_GL();
4652
4653     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4654     TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4655     glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4656     LEAVE_GL();
4657
4658     return WINED3D_OK;
4659 }
4660
4661 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
4662     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4663     GLint scissorBox[4];
4664
4665     ENTER_GL();
4666     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4667     glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
4668     pRect->left = scissorBox[0];
4669     pRect->top = scissorBox[1];
4670     pRect->right = scissorBox[0] + scissorBox[2];
4671     pRect->bottom = scissorBox[1] + scissorBox[3];
4672     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
4673     LEAVE_GL();
4674     return WINED3D_OK;
4675 }
4676
4677 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
4678     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4679     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
4680
4681     TRACE("(%p) : pDecl=%p\n", This, pDecl);
4682
4683     This->updateStateBlock->vertexDecl = pDecl;
4684     This->updateStateBlock->changed.vertexDecl = TRUE;
4685     This->updateStateBlock->set.vertexDecl = TRUE;
4686
4687     if (This->isRecordingState) {
4688         TRACE("Recording... not performing anything\n");
4689     }
4690
4691     if (NULL != pDecl) {
4692         IWineD3DVertexDeclaration_AddRef(pDecl);
4693     }
4694     if (NULL != oldDecl) {
4695         IWineD3DVertexDeclaration_Release(oldDecl);
4696     }
4697     return WINED3D_OK;
4698 }
4699
4700 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
4701     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4702
4703     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
4704
4705     *ppDecl = This->stateBlock->vertexDecl;
4706     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
4707     return WINED3D_OK;
4708 }
4709
4710 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
4711     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
4712     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
4713
4714     This->updateStateBlock->vertexShader         = pShader;
4715     This->updateStateBlock->changed.vertexShader = TRUE;
4716     This->updateStateBlock->set.vertexShader     = TRUE;
4717
4718     if (This->isRecordingState) {
4719         TRACE("Recording... not performing anything\n");
4720     }
4721
4722     if (NULL != pShader) {
4723         IWineD3DVertexShader_AddRef(pShader);
4724     }
4725     if (NULL != oldShader) {
4726         IWineD3DVertexShader_Release(oldShader);
4727     }
4728
4729     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4730     /**
4731      * TODO: merge HAL shaders context switching from prototype
4732      */
4733     return WINED3D_OK;
4734 }
4735
4736 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
4737     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4738
4739     if (NULL == ppShader) {
4740         return WINED3DERR_INVALIDCALL;
4741     }
4742     *ppShader = This->stateBlock->vertexShader;
4743     if( NULL != *ppShader)
4744         IWineD3DVertexShader_AddRef(*ppShader);
4745
4746     TRACE("(%p) : returning %p\n", This, *ppShader);
4747     return WINED3D_OK;
4748 }
4749
4750 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
4751     IWineD3DDevice *iface,
4752     UINT start,
4753     CONST BOOL *srcData,
4754     UINT count) {
4755
4756     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4757     int i, cnt = min(count, MAX_CONST_B - start);
4758
4759     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4760             iface, srcData, start, count);
4761
4762     if (srcData == NULL || cnt < 0)
4763         return WINED3DERR_INVALIDCALL;
4764
4765     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4766     for (i = 0; i < cnt; i++)
4767         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4768
4769     for (i = start; i < cnt + start; ++i) {
4770         This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
4771         This->updateStateBlock->set.vertexShaderConstantsB[i]     = TRUE;
4772     }
4773
4774     return WINED3D_OK;
4775 }
4776
4777 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
4778     IWineD3DDevice *iface,
4779     UINT start,
4780     BOOL *dstData,
4781     UINT count) {
4782
4783     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4784     int cnt = min(count, MAX_CONST_B - start);
4785
4786     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4787             iface, dstData, start, count);
4788
4789     if (dstData == NULL || cnt < 0)
4790         return WINED3DERR_INVALIDCALL;
4791
4792     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
4793     return WINED3D_OK;
4794 }
4795
4796 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
4797     IWineD3DDevice *iface,
4798     UINT start,
4799     CONST int *srcData,
4800     UINT count) {
4801
4802     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4803     int i, cnt = min(count, MAX_CONST_I - start);
4804
4805     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4806             iface, srcData, start, count);
4807
4808     if (srcData == NULL || cnt < 0)
4809         return WINED3DERR_INVALIDCALL;
4810
4811     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4812     for (i = 0; i < cnt; i++)
4813         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
4814            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4815
4816     for (i = start; i < cnt + start; ++i) {
4817         This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
4818         This->updateStateBlock->set.vertexShaderConstantsI[i]     = TRUE;
4819     }
4820
4821     return WINED3D_OK;
4822 }
4823
4824 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
4825     IWineD3DDevice *iface,
4826     UINT start,
4827     int *dstData,
4828     UINT count) {
4829
4830     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4831     int cnt = min(count, MAX_CONST_I - start);
4832
4833     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4834             iface, dstData, start, count);
4835
4836     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
4837         return WINED3DERR_INVALIDCALL;
4838
4839     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
4840     return WINED3D_OK;
4841 }
4842
4843 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
4844     IWineD3DDevice *iface,
4845     UINT start,
4846     CONST float *srcData,
4847     UINT count) {
4848
4849     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4850     int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4851
4852     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4853             iface, srcData, start, count);
4854
4855     if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
4856         return WINED3DERR_INVALIDCALL;
4857
4858     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
4859     for (i = 0; i < cnt; i++)
4860         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4861            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4862
4863     for (i = start; i < cnt + start; ++i) {
4864         if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
4865             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
4866             ptr->idx = i;
4867             list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
4868             This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
4869         }
4870         This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
4871     }
4872
4873     return WINED3D_OK;
4874 }
4875
4876 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
4877     IWineD3DDevice *iface,
4878     UINT start,
4879     float *dstData,
4880     UINT count) {
4881
4882     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4883     int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
4884
4885     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4886             iface, dstData, start, count);
4887
4888     if (dstData == NULL || cnt < 0)
4889         return WINED3DERR_INVALIDCALL;
4890
4891     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4892     return WINED3D_OK;
4893 }
4894
4895 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
4896     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
4897     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
4898     This->updateStateBlock->pixelShader         = pShader;
4899     This->updateStateBlock->changed.pixelShader = TRUE;
4900     This->updateStateBlock->set.pixelShader     = TRUE;
4901
4902     /* Handle recording of state blocks */
4903     if (This->isRecordingState) {
4904         TRACE("Recording... not performing anything\n");
4905     }
4906
4907     if (NULL != pShader) {
4908         IWineD3DPixelShader_AddRef(pShader);
4909     }
4910     if (NULL != oldShader) {
4911         IWineD3DPixelShader_Release(oldShader);
4912     }
4913
4914     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
4915     /**
4916      * TODO: merge HAL shaders context switching from prototype
4917      */
4918     return WINED3D_OK;
4919 }
4920
4921 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
4922     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4923
4924     if (NULL == ppShader) {
4925         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
4926         return WINED3DERR_INVALIDCALL;
4927     }
4928
4929     *ppShader =  This->stateBlock->pixelShader;
4930     if (NULL != *ppShader) {
4931         IWineD3DPixelShader_AddRef(*ppShader);
4932     }
4933     TRACE("(%p) : returning %p\n", This, *ppShader);
4934     return WINED3D_OK;
4935 }
4936
4937 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
4938     IWineD3DDevice *iface,
4939     UINT start,
4940     CONST BOOL *srcData,
4941     UINT count) {
4942
4943     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4944     int i, cnt = min(count, MAX_CONST_B - start);
4945
4946     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4947             iface, srcData, start, count);
4948
4949     if (srcData == NULL || cnt < 0)
4950         return WINED3DERR_INVALIDCALL;
4951
4952     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
4953     for (i = 0; i < cnt; i++)
4954         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
4955
4956     for (i = start; i < cnt + start; ++i) {
4957         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
4958         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
4959     }
4960
4961     return WINED3D_OK;
4962 }
4963
4964 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
4965     IWineD3DDevice *iface,
4966     UINT start,
4967     BOOL *dstData,
4968     UINT count) {
4969
4970     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4971     int cnt = min(count, MAX_CONST_B - start);
4972
4973     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4974             iface, dstData, start, count);
4975
4976     if (dstData == NULL || cnt < 0)
4977         return WINED3DERR_INVALIDCALL;
4978
4979     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
4980     return WINED3D_OK;
4981 }
4982
4983 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
4984     IWineD3DDevice *iface,
4985     UINT start,
4986     CONST int *srcData,
4987     UINT count) {
4988
4989     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4990     int i, cnt = min(count, MAX_CONST_I - start);
4991
4992     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4993             iface, srcData, start, count);
4994
4995     if (srcData == NULL || cnt < 0)
4996         return WINED3DERR_INVALIDCALL;
4997
4998     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
4999     for (i = 0; i < cnt; i++)
5000         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
5001            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5002
5003     for (i = start; i < cnt + start; ++i) {
5004         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
5005         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
5006     }
5007
5008     return WINED3D_OK;
5009 }
5010
5011 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
5012     IWineD3DDevice *iface,
5013     UINT start,
5014     int *dstData,
5015     UINT count) {
5016
5017     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5018     int cnt = min(count, MAX_CONST_I - start);
5019
5020     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5021             iface, dstData, start, count);
5022
5023     if (dstData == NULL || cnt < 0)
5024         return WINED3DERR_INVALIDCALL;
5025
5026     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
5027     return WINED3D_OK;
5028 }
5029
5030 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
5031     IWineD3DDevice *iface,
5032     UINT start,
5033     CONST float *srcData,
5034     UINT count) {
5035
5036     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5037     int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5038
5039     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
5040             iface, srcData, start, count);
5041
5042     if (srcData == NULL || cnt < 0)
5043         return WINED3DERR_INVALIDCALL;
5044
5045     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
5046     for (i = 0; i < cnt; i++)
5047         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
5048            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
5049
5050     for (i = start; i < cnt + start; ++i) {
5051         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
5052             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
5053             ptr->idx = i;
5054             list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
5055             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
5056         }
5057         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
5058     }
5059
5060     return WINED3D_OK;
5061 }
5062
5063 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
5064     IWineD3DDevice *iface,
5065     UINT start,
5066     float *dstData,
5067     UINT count) {
5068
5069     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5070     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
5071
5072     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
5073             iface, dstData, start, count);
5074
5075     if (dstData == NULL || cnt < 0)
5076         return WINED3DERR_INVALIDCALL;
5077
5078     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
5079     return WINED3D_OK;
5080 }
5081
5082 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
5083 static HRESULT
5084 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
5085     char *dest_ptr, *dest_conv = NULL;
5086     unsigned int i;
5087     DWORD DestFVF = dest->fvf;
5088     D3DVIEWPORT9 vp;
5089     D3DMATRIX mat, proj_mat, view_mat, world_mat;
5090     BOOL doClip;
5091     int numTextures;
5092
5093     if (SrcFVF & D3DFVF_NORMAL) {
5094         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
5095     }
5096
5097     if ( (SrcFVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
5098         ERR("Source has no position mask\n");
5099         return WINED3DERR_INVALIDCALL;
5100     }
5101
5102     /* We might access VBOs from this code, so hold the lock */
5103     ENTER_GL();
5104
5105     if (dest->resource.allocatedMemory == NULL) {
5106         /* This may happen if we do direct locking into a vbo. Unlikely,
5107          * but theoretically possible(ddraw processvertices test)
5108          */
5109         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
5110         if(!dest->resource.allocatedMemory) {
5111             LEAVE_GL();
5112             ERR("Out of memory\n");
5113             return E_OUTOFMEMORY;
5114         }
5115         if(dest->vbo) {
5116             void *src;
5117             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5118             checkGLcall("glBindBufferARB");
5119             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5120             if(src) {
5121                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
5122             }
5123             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5124             checkGLcall("glUnmapBufferARB");
5125         }
5126     }
5127
5128     /* Get a pointer into the destination vbo(create one if none exists) and
5129      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
5130      */
5131     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
5132         CreateVBO(dest);
5133     }
5134
5135     if(dest->vbo) {
5136         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
5137         dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
5138         if(!dest_conv) {
5139             ERR("glMapBuffer failed\n");
5140             /* Continue without storing converted vertices */
5141         }
5142     }
5143
5144     /* Should I clip?
5145      * a) D3DRS_CLIPPING is enabled
5146      * b) WINED3DVOP_CLIP is passed
5147      */
5148     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
5149         static BOOL warned = FALSE;
5150         /*
5151          * The clipping code is not quite correct. Some things need
5152          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
5153          * so disable clipping for now.
5154          * (The graphics in Half-Life are broken, and my processvertices
5155          *  test crashes with IDirect3DDevice3)
5156         doClip = TRUE;
5157          */
5158         doClip = FALSE;
5159         if(!warned) {
5160            warned = TRUE;
5161            FIXME("Clipping is broken and disabled for now\n");
5162         }
5163     } else doClip = FALSE;
5164     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5165     if(dest_conv) {
5166         dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
5167     }
5168
5169     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5170                                  WINED3DTS_VIEW,
5171                                  &view_mat);
5172     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5173                                  WINED3DTS_PROJECTION,
5174                                  &proj_mat);
5175     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
5176                                  WINED3DTS_WORLDMATRIX(0),
5177                                  &world_mat);
5178
5179     TRACE("View mat:\n");
5180     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); \
5181     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); \
5182     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); \
5183     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); \
5184
5185     TRACE("Proj mat:\n");
5186     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); \
5187     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); \
5188     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); \
5189     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); \
5190
5191     TRACE("World mat:\n");
5192     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); \
5193     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); \
5194     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); \
5195     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); \
5196
5197     /* Get the viewport */
5198     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
5199     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
5200           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
5201
5202     multiply_matrix(&mat,&view_mat,&world_mat);
5203     multiply_matrix(&mat,&proj_mat,&mat);
5204
5205     numTextures = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
5206
5207     for (i = 0; i < dwCount; i+= 1) {
5208         unsigned int tex_index;
5209
5210         if ( ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ ) ||
5211              ((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW ) ) {
5212             /* The position first */
5213             float *p =
5214               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
5215             float x, y, z, rhw;
5216             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
5217
5218             /* Multiplication with world, view and projection matrix */
5219             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);
5220             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);
5221             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);
5222             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);
5223
5224             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
5225
5226             /* WARNING: The following things are taken from d3d7 and were not yet checked
5227              * against d3d8 or d3d9!
5228              */
5229
5230             /* Clipping conditions: From
5231              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
5232              *
5233              * A vertex is clipped if it does not match the following requirements
5234              * -rhw < x <= rhw
5235              * -rhw < y <= rhw
5236              *    0 < z <= rhw
5237              *    0 < rhw ( Not in d3d7, but tested in d3d7)
5238              *
5239              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
5240              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
5241              *
5242              */
5243
5244             if( !doClip ||
5245                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
5246                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
5247                   ( rhw > eps ) ) ) {
5248
5249                 /* "Normal" viewport transformation (not clipped)
5250                  * 1) The values are divided by rhw
5251                  * 2) The y axis is negative, so multiply it with -1
5252                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
5253                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
5254                  * 4) Multiply x with Width/2 and add Width/2
5255                  * 5) The same for the height
5256                  * 6) Add the viewpoint X and Y to the 2D coordinates and
5257                  *    The minimum Z value to z
5258                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
5259                  *
5260                  * Well, basically it's simply a linear transformation into viewport
5261                  * coordinates
5262                  */
5263
5264                 x /= rhw;
5265                 y /= rhw;
5266                 z /= rhw;
5267
5268                 y *= -1;
5269
5270                 x *= vp.Width / 2;
5271                 y *= vp.Height / 2;
5272                 z *= vp.MaxZ - vp.MinZ;
5273
5274                 x += vp.Width / 2 + vp.X;
5275                 y += vp.Height / 2 + vp.Y;
5276                 z += vp.MinZ;
5277
5278                 rhw = 1 / rhw;
5279             } else {
5280                 /* That vertex got clipped
5281                  * Contrary to OpenGL it is not dropped completely, it just
5282                  * undergoes a different calculation.
5283                  */
5284                 TRACE("Vertex got clipped\n");
5285                 x += rhw;
5286                 y += rhw;
5287
5288                 x  /= 2;
5289                 y  /= 2;
5290
5291                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
5292                  * outside of the main vertex buffer memory. That needs some more
5293                  * investigation...
5294                  */
5295             }
5296
5297             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
5298
5299
5300             ( (float *) dest_ptr)[0] = x;
5301             ( (float *) dest_ptr)[1] = y;
5302             ( (float *) dest_ptr)[2] = z;
5303             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
5304
5305             dest_ptr += 3 * sizeof(float);
5306
5307             if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5308                 dest_ptr += sizeof(float);
5309             }
5310
5311             if(dest_conv) {
5312                 float w = 1 / rhw;
5313                 ( (float *) dest_conv)[0] = x * w;
5314                 ( (float *) dest_conv)[1] = y * w;
5315                 ( (float *) dest_conv)[2] = z * w;
5316                 ( (float *) dest_conv)[3] = w;
5317
5318                 dest_conv += 3 * sizeof(float);
5319
5320                 if((DestFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
5321                     dest_conv += sizeof(float);
5322                 }
5323             }
5324         }
5325         if (DestFVF & D3DFVF_PSIZE) {
5326             dest_ptr += sizeof(DWORD);
5327             if(dest_conv) dest_conv += sizeof(DWORD);
5328         }
5329         if (DestFVF & D3DFVF_NORMAL) {
5330             float *normal =
5331               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
5332             /* AFAIK this should go into the lighting information */
5333             FIXME("Didn't expect the destination to have a normal\n");
5334             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
5335             if(dest_conv) {
5336                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
5337             }
5338         }
5339
5340         if (DestFVF & D3DFVF_DIFFUSE) {
5341             DWORD *color_d = 
5342               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
5343             if(!color_d) {
5344                 static BOOL warned = FALSE;
5345
5346                 if(!warned) {
5347                     ERR("No diffuse color in source, but destination has one\n");
5348                     warned = TRUE;
5349                 }
5350
5351                 *( (DWORD *) dest_ptr) = 0xffffffff;
5352                 dest_ptr += sizeof(DWORD);
5353
5354                 if(dest_conv) {
5355                     *( (DWORD *) dest_conv) = 0xffffffff;
5356                     dest_conv += sizeof(DWORD);
5357                 }
5358             }
5359             else {
5360                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
5361                 if(dest_conv) {
5362                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
5363                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
5364                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
5365                     dest_conv += sizeof(DWORD);
5366                 }
5367             }
5368         }
5369
5370         if (DestFVF & D3DFVF_SPECULAR) { 
5371             /* What's the color value in the feedback buffer? */
5372             DWORD *color_s = 
5373               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
5374             if(!color_s) {
5375                 static BOOL warned = FALSE;
5376
5377                 if(!warned) {
5378                     ERR("No specular color in source, but destination has one\n");
5379                     warned = TRUE;
5380                 }
5381
5382                 *( (DWORD *) dest_ptr) = 0xFF000000;
5383                 dest_ptr += sizeof(DWORD);
5384
5385                 if(dest_conv) {
5386                     *( (DWORD *) dest_conv) = 0xFF000000;
5387                     dest_conv += sizeof(DWORD);
5388                 }
5389             }
5390             else {
5391                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
5392                 if(dest_conv) {
5393                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
5394                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
5395                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
5396                     dest_conv += sizeof(DWORD);
5397                 }
5398             }
5399         }
5400
5401         for (tex_index = 0; tex_index < numTextures; tex_index++) {
5402             float *tex_coord =
5403               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
5404                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
5405             if(!tex_coord) {
5406                 ERR("No source texture, but destination requests one\n");
5407                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5408                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
5409             }
5410             else {
5411                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5412                 if(dest_conv) {
5413                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
5414                 }
5415             }
5416         }
5417     }
5418
5419     if(dest_conv) {
5420         GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5421         checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
5422     }
5423
5424     LEAVE_GL();
5425
5426     return WINED3D_OK;
5427 }
5428 #undef copy_and_next
5429
5430 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
5431     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5432     IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
5433     WineDirect3DVertexStridedData strided;
5434     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
5435
5436     if (!SrcImpl) {
5437         WARN("NULL source vertex buffer\n");
5438         return WINED3DERR_INVALIDCALL;
5439     }
5440     /* We don't need the source vbo because this buffer is only used as
5441      * a source for ProcessVertices. Avoid wasting resources by converting the
5442      * buffer and loading the VBO
5443      */
5444     if(SrcImpl->vbo) {
5445         TRACE("Releaseing the source vbo, it won't be needed\n");
5446
5447         if(!SrcImpl->resource.allocatedMemory) {
5448             /* Rescue the data from the buffer */
5449             void *src;
5450             SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
5451             if(!SrcImpl->resource.allocatedMemory) {
5452                 ERR("Out of memory\n");
5453                 return E_OUTOFMEMORY;
5454             }
5455
5456             ENTER_GL();
5457             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
5458             checkGLcall("glBindBufferARB");
5459
5460             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
5461             if(src) {
5462                 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
5463             }
5464
5465             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
5466             checkGLcall("glUnmapBufferARB");
5467         } else {
5468             ENTER_GL();
5469         }
5470
5471         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
5472         checkGLcall("glBindBufferARB");
5473         GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
5474         checkGLcall("glDeleteBuffersARB");
5475         LEAVE_GL();
5476
5477         SrcImpl->vbo = 0;
5478     }
5479
5480     memset(&strided, 0, sizeof(strided));
5481     primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
5482
5483     return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
5484 }
5485
5486 /*****
5487  * Apply / Get / Set Texture Stage States
5488  * TODO: Verify against dx9 definitions
5489  *****/
5490
5491 /* 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 */
5492 static void WINAPI IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type) {
5493     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5494     DWORD Value = This->updateStateBlock->textureState[Stage][Type];
5495     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5496
5497     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5498
5499     /* Check that the stage is within limits  */
5500     if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
5501         TRACE("Attempt to access invalid texture rejected\n");
5502         return;
5503     }
5504
5505     ENTER_GL();
5506
5507     switch (Type) {
5508     case WINED3DTSS_ALPHAOP               :
5509     case WINED3DTSS_COLOROP               :
5510         /* nothing to do as moved to drawprim for now */
5511         break;
5512     case WINED3DTSS_ADDRESSW              :
5513 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
5514             if (Value < minLookup[WINELOOKUP_WARPPARAM] || Value > maxLookup[WINELOOKUP_WARPPARAM]) {
5515                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %d, state %d\n", Value, Type);
5516
5517             } else {
5518                 GLint wrapParm = stateLookup[WINELOOKUP_WARPPARAM][Value - minLookup[WINELOOKUP_WARPPARAM]];
5519                 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
5520                 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
5521                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
5522             }
5523 #endif
5524     case WINED3DTSS_TEXCOORDINDEX         :
5525         {
5526             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
5527
5528             /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
5529                   one flag, you can still specify an index value, which the system uses to
5530                   determine the texture wrapping mode.
5531                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
5532                   means use the vertex position (camera-space) as the input texture coordinates
5533                   for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
5534                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
5535                   to the TEXCOORDINDEX value */
5536
5537             /**
5538              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
5539              */
5540             switch (Value & 0xFFFF0000) {
5541             case D3DTSS_TCI_PASSTHRU:
5542                 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5543                 glDisable(GL_TEXTURE_GEN_S);
5544                 glDisable(GL_TEXTURE_GEN_T);
5545                 glDisable(GL_TEXTURE_GEN_R);
5546                 glDisable(GL_TEXTURE_GEN_Q);
5547                 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5548                 break;
5549
5550             case D3DTSS_TCI_CAMERASPACEPOSITION:
5551                 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5552                     as the input texture coordinates for this stage's texture transformation. This
5553                     equates roughly to EYE_LINEAR                                                  */
5554                 {
5555                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5556                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5557                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5558                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5559                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5560     
5561                     glMatrixMode(GL_MODELVIEW);
5562                     glPushMatrix();
5563                     glLoadIdentity();
5564                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5565                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5566                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5567                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5568                     glPopMatrix();
5569     
5570                     TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5571                     glEnable(GL_TEXTURE_GEN_S);
5572                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5573                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5574                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5575                     glEnable(GL_TEXTURE_GEN_T);
5576                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5577                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5578                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5579                     glEnable(GL_TEXTURE_GEN_R);
5580                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5581                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
5582                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5583                 }
5584                 break;
5585
5586             case D3DTSS_TCI_CAMERASPACENORMAL:
5587                 {
5588                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5589                         float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5590                         float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5591                         float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5592                         float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5593                         TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5594         
5595                         glMatrixMode(GL_MODELVIEW);
5596                         glPushMatrix();
5597                         glLoadIdentity();
5598                         glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5599                         glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5600                         glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5601                         glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5602                         glPopMatrix();
5603         
5604                         glEnable(GL_TEXTURE_GEN_S);
5605                         checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5606                         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5607                         checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5608                         glEnable(GL_TEXTURE_GEN_T);
5609                         checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5610                         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5611                         checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5612                         glEnable(GL_TEXTURE_GEN_R);
5613                         checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5614                         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
5615                         checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5616                     }
5617                 }
5618                 break;
5619
5620             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
5621                 {
5622                     if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
5623                     float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
5624                     float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
5625                     float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
5626                     float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
5627                     TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5628     
5629                     glMatrixMode(GL_MODELVIEW);
5630                     glPushMatrix();
5631                     glLoadIdentity();
5632                     glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
5633                     glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
5634                     glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
5635                     glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
5636                     glPopMatrix();
5637     
5638                     glEnable(GL_TEXTURE_GEN_S);
5639                     checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5640                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5641                     checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5642                     glEnable(GL_TEXTURE_GEN_T);
5643                     checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5644                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5645                     checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5646                     glEnable(GL_TEXTURE_GEN_R);
5647                     checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5648                     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
5649                     checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5650                     }
5651                 }
5652                 break;
5653
5654             /* Unhandled types: */
5655             default:
5656                 /* Todo: */
5657                 /* ? disable GL_TEXTURE_GEN_n ? */
5658                 glDisable(GL_TEXTURE_GEN_S);
5659                 glDisable(GL_TEXTURE_GEN_T);
5660                 glDisable(GL_TEXTURE_GEN_R);
5661                 glDisable(GL_TEXTURE_GEN_Q);
5662                 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", Value);
5663                 break;
5664             }
5665         }
5666         break;
5667
5668         /* Unhandled */
5669     case WINED3DTSS_TEXTURETRANSFORMFLAGS :
5670         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);
5671         break;
5672
5673     case WINED3DTSS_BUMPENVMAT00          :
5674     case WINED3DTSS_BUMPENVMAT01          :
5675         TRACE("BUMPENVMAT0%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
5676         break;
5677     case WINED3DTSS_BUMPENVMAT10          :
5678     case WINED3DTSS_BUMPENVMAT11          :
5679         TRACE("BUMPENVMAT1%u Stage=%d, Type=%d, Value =%d\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
5680         break;
5681
5682     case WINED3DTSS_BUMPENVLSCALE         :
5683       TRACE("BUMPENVLSCALE Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5684       break;
5685
5686     case WINED3DTSS_BUMPENVLOFFSET        :
5687       TRACE("BUMPENVLOFFSET Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5688       break;
5689
5690     case WINED3DTSS_RESULTARG             :
5691       TRACE("RESULTARG Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5692       break;
5693
5694     default:
5695         /* Put back later: FIXME("(%p) : stub, Stage=%d, Type=%d, Value =%d\n", This, Stage, Type, Value); */
5696         TRACE("Still a stub, Stage=%d, Type=%d, Value =%d\n", Stage, Type, Value);
5697     }
5698
5699     LEAVE_GL();
5700
5701     return;
5702 }
5703
5704 /*****
5705  * Get / Set Texture Stage States
5706  * TODO: Verify against dx9 definitions
5707  *****/
5708 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
5709     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5710
5711     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5712
5713     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
5714
5715     /* Reject invalid texture units */
5716     if (Stage >= GL_LIMITS(texture_stages)) {
5717         TRACE("Attempt to access invalid texture rejected\n");
5718         return WINED3DERR_INVALIDCALL;
5719     }
5720
5721     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
5722     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
5723     This->updateStateBlock->textureState[Stage][Type]         = Value;
5724
5725     return WINED3D_OK;
5726 }
5727
5728 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
5729     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5730     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
5731     *pValue = This->updateStateBlock->textureState[Stage][Type];
5732     return WINED3D_OK;
5733 }
5734
5735 /*****
5736  * Get / Set Texture
5737  *****/
5738 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
5739
5740     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5741     IWineD3DBaseTexture   *oldTexture;
5742
5743     oldTexture = This->updateStateBlock->textures[Stage];
5744     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
5745
5746 #if 0 /* TODO: check so vertex textures */
5747     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
5748         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
5749         return WINED3D_OK;
5750     }
5751 #endif
5752
5753     /* Reject invalid texture units */
5754     if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
5755         WARN("Attempt to access invalid texture rejected\n");
5756         return WINED3DERR_INVALIDCALL;
5757     }
5758
5759     if(pTexture != NULL) {
5760         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
5761          */
5762         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
5763             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
5764             return WINED3DERR_INVALIDCALL;
5765         }
5766     }
5767
5768     oldTexture = This->updateStateBlock->textures[Stage];
5769     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
5770     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
5771
5772     This->updateStateBlock->set.textures[Stage]     = TRUE;
5773     This->updateStateBlock->changed.textures[Stage] = TRUE;
5774     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
5775     This->updateStateBlock->textures[Stage]         = pTexture;
5776
5777     /* Handle recording of state blocks */
5778     if (This->isRecordingState) {
5779         TRACE("Recording... not performing anything\n");
5780         return WINED3D_OK;
5781     }
5782
5783     /** NOTE: MSDN says that setTexture increases the reference count,
5784     * and the the application nust set the texture back to null (or have a leaky application),
5785     * This means we should pass the refcount up to the parent
5786      *******************************/
5787     if (NULL != This->updateStateBlock->textures[Stage]) {
5788         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
5789     }
5790
5791     if (NULL != oldTexture) {
5792         IWineD3DBaseTexture_Release(oldTexture);
5793     }
5794
5795     /* Reset color keying */
5796     if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
5797         BOOL enable_ckey = FALSE;
5798
5799         if(pTexture) {
5800             IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)pTexture)->surfaces[0];
5801             if(surf->CKeyFlags & DDSD_CKSRCBLT) enable_ckey = TRUE;
5802         }
5803
5804         if(enable_ckey) {
5805             glAlphaFunc(GL_NOTEQUAL, 0.0);
5806             checkGLcall("glAlphaFunc");
5807         }
5808     }
5809
5810     return WINED3D_OK;
5811 }
5812
5813 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
5814     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5815     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
5816
5817     /* Reject invalid texture units */
5818     if (Stage >= GL_LIMITS(sampler_stages)) {
5819         TRACE("Attempt to access invalid texture rejected\n");
5820         return WINED3DERR_INVALIDCALL;
5821     }
5822     *ppTexture=This->updateStateBlock->textures[Stage];
5823     if (*ppTexture)
5824         IWineD3DBaseTexture_AddRef(*ppTexture);
5825     else
5826         return WINED3DERR_INVALIDCALL;
5827     return WINED3D_OK;
5828 }
5829
5830 /*****
5831  * Get Back Buffer
5832  *****/
5833 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
5834                                                 IWineD3DSurface **ppBackBuffer) {
5835     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5836     IWineD3DSwapChain *swapChain;
5837     HRESULT hr;
5838
5839     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
5840
5841     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
5842     if (hr == WINED3D_OK) {
5843         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
5844             IWineD3DSwapChain_Release(swapChain);
5845     } else {
5846         *ppBackBuffer = NULL;
5847     }
5848     return hr;
5849 }
5850
5851 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
5852     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5853     WARN("(%p) : stub, calling idirect3d for now\n", This);
5854     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
5855 }
5856
5857 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
5858     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5859     IWineD3DSwapChain *swapChain;
5860     HRESULT hr;
5861
5862     if(iSwapChain > 0) {
5863         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5864         if (hr == WINED3D_OK) {
5865             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
5866             IWineD3DSwapChain_Release(swapChain);
5867         } else {
5868             FIXME("(%p) Error getting display mode\n", This);
5869         }
5870     } else {
5871         /* Don't read the real display mode,
5872            but return the stored mode instead. X11 can't change the color
5873            depth, and some apps are pretty angry if they SetDisplayMode from
5874            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5875
5876            Also don't relay to the swapchain because with ddraw it's possible
5877            that there isn't a swapchain at all */
5878         pMode->Width = This->ddraw_width;
5879         pMode->Height = This->ddraw_height;
5880         pMode->Format = This->ddraw_format;
5881         pMode->RefreshRate = 0;
5882         hr = WINED3D_OK;
5883     }
5884
5885     return hr;
5886 }
5887
5888 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
5889     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5890     TRACE("(%p)->(%p)\n", This, hWnd);
5891
5892     This->ddraw_window = hWnd;
5893     return WINED3D_OK;
5894 }
5895
5896 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
5897     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5898     TRACE("(%p)->(%p)\n", This, hWnd);
5899
5900     *hWnd = This->ddraw_window;
5901     return WINED3D_OK;
5902 }
5903
5904 /*****
5905  * Stateblock related functions
5906  *****/
5907
5908 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
5909     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5910     IWineD3DStateBlockImpl *object;
5911     HRESULT temp_result;
5912     
5913     TRACE("(%p)\n", This);
5914     
5915     if (This->isRecordingState) {
5916         return WINED3DERR_INVALIDCALL;
5917     }
5918     
5919     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
5920     if (NULL == object ) {
5921         FIXME("(%p)Error allocating memory for stateblock\n", This);
5922         return E_OUTOFMEMORY;
5923     }
5924     TRACE("(%p) created object %p\n", This, object);
5925     object->wineD3DDevice= This;
5926     /** FIXME: object->parent       = parent; **/
5927     object->parent       = NULL;
5928     object->blockType    = WINED3DSBT_ALL;
5929     object->ref          = 1;
5930     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
5931     
5932     temp_result = allocate_shader_constants(object);
5933     if (WINED3D_OK != temp_result)
5934         return temp_result;
5935
5936     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
5937     This->updateStateBlock = object;
5938     This->isRecordingState = TRUE;
5939
5940     TRACE("(%p) recording stateblock %p\n",This , object);
5941     return WINED3D_OK;
5942 }
5943
5944 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
5945     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5946
5947     if (!This->isRecordingState) {
5948         FIXME("(%p) not recording! returning error\n", This);
5949         *ppStateBlock = NULL;
5950         return WINED3DERR_INVALIDCALL;
5951     }
5952
5953     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
5954     This->isRecordingState = FALSE;
5955     This->updateStateBlock = This->stateBlock;
5956     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
5957     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5958     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
5959     return WINED3D_OK;
5960 }
5961
5962 /*****
5963  * Scene related functions
5964  *****/
5965 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
5966     /* At the moment we have no need for any functionality at the beginning
5967        of a scene                                                          */
5968     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5969     TRACE("(%p) : stub\n", This);
5970     return WINED3D_OK;
5971 }
5972
5973 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
5974     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5975     TRACE("(%p)\n", This);
5976     ENTER_GL();
5977     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5978     glFlush();
5979     checkGLcall("glFlush");
5980
5981     TRACE("End Scene\n");
5982     if(This->renderTarget != NULL) {
5983
5984         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5985         IUnknown *targetContainer = NULL;
5986         if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
5987             || WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
5988             TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
5989             /** always dirtify for now. we must find a better way to see that surface have been modified
5990             (Modifications should will only occur via draw-primitive, but we do need better locking
5991             switching to render-to-texture should remove the overhead though.
5992             */
5993             IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
5994             IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
5995             IWineD3DSurface_PreLoad(This->renderTarget);
5996             IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
5997             IUnknown_Release(targetContainer);
5998         }
5999     }
6000     This->sceneEnded = TRUE;
6001     LEAVE_GL();
6002     return WINED3D_OK;
6003 }
6004
6005 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
6006                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
6007                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
6008     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6009     IWineD3DSwapChain *swapChain = NULL;
6010     int i;
6011     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
6012
6013     TRACE("(%p) Presenting the frame\n", This);
6014
6015     for(i = 0 ; i < swapchains ; i ++) {
6016
6017         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
6018         TRACE("presentinng chain %d, %p\n", i, swapChain);
6019         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
6020         IWineD3DSwapChain_Release(swapChain);
6021     }
6022
6023     return WINED3D_OK;
6024 }
6025
6026 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
6027                                         DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
6028     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6029
6030     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
6031       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
6032       when the depth-buffer format does not contain stencil buffer information, this method fails. */
6033     GLbitfield     glMask = 0;
6034     GLboolean      old_ztest;
6035     GLfloat        old_z_clear_value;
6036     GLint          old_stencil_clear_value;
6037     GLfloat        old_color_clear_value[4];
6038     unsigned int   i;
6039     CONST D3DRECT* curRect;
6040
6041     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
6042           Count, pRects, Flags, Z, Stencil);
6043
6044     ENTER_GL();
6045
6046     glEnable(GL_SCISSOR_TEST);
6047     checkGLcall("glEnable GL_SCISSOR_TEST");
6048
6049     if (Count > 0 && pRects) {
6050         curRect = pRects;
6051     } else {
6052         curRect = NULL;
6053     }
6054
6055     /* Only set the values up once, as they are not changing */
6056     if (Flags & D3DCLEAR_STENCIL) {
6057         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
6058         glClearStencil(Stencil);
6059         checkGLcall("glClearStencil");
6060         glMask = glMask | GL_STENCIL_BUFFER_BIT;
6061         glStencilMask(0xFFFFFFFF);
6062     }
6063
6064     if (Flags & D3DCLEAR_ZBUFFER) {
6065         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
6066         glDepthMask(GL_TRUE);
6067         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
6068         glClearDepth(Z);
6069         checkGLcall("glClearDepth");
6070         glMask = glMask | GL_DEPTH_BUFFER_BIT;
6071     }
6072
6073     if (Flags & D3DCLEAR_TARGET) {
6074         TRACE("Clearing screen with glClear to color %x\n", Color);
6075         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
6076         glClearColor(D3DCOLOR_R(Color),
6077                      D3DCOLOR_G(Color),
6078                      D3DCOLOR_B(Color),
6079                      D3DCOLOR_A(Color));
6080         checkGLcall("glClearColor");
6081
6082         /* Clear ALL colors! */
6083         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6084         glMask = glMask | GL_COLOR_BUFFER_BIT;
6085     }
6086
6087     /* Now process each rect in turn */
6088     for (i = 0; i < Count || i == 0; i++) {
6089
6090         if (curRect) {
6091             /* Note gl uses lower left, width/height */
6092             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
6093                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
6094                   curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6095                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6096             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
6097                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
6098             checkGLcall("glScissor");
6099         } else {
6100             glScissor(This->stateBlock->viewport.X,
6101                       (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - 
6102                       (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
6103                       This->stateBlock->viewport.Width,
6104                       This->stateBlock->viewport.Height);
6105             checkGLcall("glScissor");
6106         }
6107
6108         /* Clear the selected rectangle (or full screen) */
6109         glClear(glMask);
6110         checkGLcall("glClear");
6111
6112         /* Step to the next rectangle */
6113         if (curRect) curRect = curRect + sizeof(D3DRECT);
6114     }
6115
6116     /* Restore the old values (why..?) */
6117     if (Flags & D3DCLEAR_STENCIL) {
6118         glClearStencil(old_stencil_clear_value);
6119         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
6120     }
6121     if (Flags & D3DCLEAR_ZBUFFER) {
6122         glDepthMask(old_ztest);
6123         glClearDepth(old_z_clear_value);
6124     }
6125     if (Flags & D3DCLEAR_TARGET) {
6126         glClearColor(old_color_clear_value[0],
6127                      old_color_clear_value[1],
6128                      old_color_clear_value[2],
6129                      old_color_clear_value[3]);
6130         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
6131                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
6132                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
6133                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
6134     }
6135
6136     glDisable(GL_SCISSOR_TEST);
6137     checkGLcall("glDisable");
6138     LEAVE_GL();
6139
6140     return WINED3D_OK;
6141 }
6142
6143 /*****
6144  * Drawing functions
6145  *****/
6146 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
6147                                                 UINT PrimitiveCount) {
6148
6149     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6150     This->stateBlock->streamIsUP = FALSE;
6151
6152     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
6153                                debug_d3dprimitivetype(PrimitiveType),
6154                                StartVertex, PrimitiveCount);
6155     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
6156                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */, NULL);
6157
6158
6159     return WINED3D_OK;
6160 }
6161
6162 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
6163 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
6164                                                            D3DPRIMITIVETYPE PrimitiveType,
6165                                                            INT baseVIndex, UINT minIndex,
6166                                                            UINT NumVertices, UINT startIndex, UINT primCount) {
6167
6168     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
6169     UINT                 idxStride = 2;
6170     IWineD3DIndexBuffer *pIB;
6171     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
6172
6173     pIB = This->stateBlock->pIndexData;
6174     This->stateBlock->streamIsUP = FALSE;
6175
6176     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This,
6177           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6178           minIndex, NumVertices, startIndex, baseVIndex, primCount);
6179
6180     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
6181     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
6182         idxStride = 2;
6183     } else {
6184         idxStride = 4;
6185     }
6186
6187     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex, NumVertices, startIndex,
6188                    idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex, NULL);
6189
6190     return WINED3D_OK;
6191 }
6192
6193 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6194                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
6195                                                     UINT VertexStreamZeroStride) {
6196     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6197
6198     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
6199              debug_d3dprimitivetype(PrimitiveType),
6200              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
6201
6202     /* release the stream source */
6203     if (This->stateBlock->streamSource[0] != NULL) {
6204         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6205     }
6206
6207     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6208     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6209     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6210     This->stateBlock->streamIsUP = TRUE;
6211
6212     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
6213                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */, NULL);
6214
6215     /* MSDN specifies stream zero settings must be set to NULL */
6216     This->stateBlock->streamStride[0] = 0;
6217     This->stateBlock->streamSource[0] = NULL;
6218
6219     /*stream zero settings set to null at end, as per the msdn */
6220     return WINED3D_OK;
6221 }
6222
6223 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
6224                                                              UINT MinVertexIndex, UINT NumVertices,
6225                                                              UINT PrimitiveCount, CONST void* pIndexData,
6226                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
6227                                                              UINT VertexStreamZeroStride) {
6228     int                 idxStride;
6229     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6230
6231     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
6232              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
6233              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
6234              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
6235
6236     if (IndexDataFormat == WINED3DFMT_INDEX16) {
6237         idxStride = 2;
6238     } else {
6239         idxStride = 4;
6240     }
6241
6242     /* release the stream and index data */
6243     if (This->stateBlock->streamSource[0] != NULL) {
6244         IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
6245     }
6246     if (This->stateBlock->pIndexData) {
6247         IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
6248     }
6249
6250     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
6251     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
6252     This->stateBlock->streamIsUP = TRUE;
6253     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
6254
6255     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex, NULL);
6256
6257     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
6258     This->stateBlock->streamSource[0] = NULL;
6259     This->stateBlock->streamStride[0] = 0;
6260     This->stateBlock->pIndexData = NULL;
6261
6262     return WINED3D_OK;
6263 }
6264
6265 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
6266
6267     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0, DrawPrimStrideData);
6268     return WINED3D_OK;
6269 }
6270  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
6271 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
6272     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6273     HRESULT hr = WINED3D_OK;
6274     WINED3DRESOURCETYPE sourceType;
6275     WINED3DRESOURCETYPE destinationType;
6276     int i ,levels;
6277
6278     /* TODO: think about moving the code into IWineD3DBaseTexture  */
6279
6280     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
6281
6282     /* verify that the source and destination textures aren't NULL */
6283     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
6284         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
6285              This, pSourceTexture, pDestinationTexture);
6286         hr = WINED3DERR_INVALIDCALL;
6287     }
6288
6289     if (pSourceTexture == pDestinationTexture) {
6290         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
6291              This, pSourceTexture, pDestinationTexture);
6292         hr = WINED3DERR_INVALIDCALL;
6293     }
6294     /* Verify that the source and destination textures are the same type */
6295     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
6296     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
6297
6298     if (sourceType != destinationType) {
6299         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
6300              This);
6301         hr = WINED3DERR_INVALIDCALL;
6302     }
6303
6304     /* check that both textures have the identical numbers of levels  */
6305     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
6306         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
6307         hr = WINED3DERR_INVALIDCALL;
6308     }
6309
6310     if (WINED3D_OK == hr) {
6311
6312         /* Make sure that the destination texture is loaded */
6313         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
6314
6315         /* Update every surface level of the texture */
6316         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
6317
6318         switch (sourceType) {
6319         case WINED3DRTYPE_TEXTURE:
6320             {
6321                 IWineD3DSurface *srcSurface;
6322                 IWineD3DSurface *destSurface;
6323
6324                 for (i = 0 ; i < levels ; ++i) {
6325                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
6326                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
6327                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6328                     IWineD3DSurface_Release(srcSurface);
6329                     IWineD3DSurface_Release(destSurface);
6330                     if (WINED3D_OK != hr) {
6331                         WARN("(%p) : Call to update surface failed\n", This);
6332                         return hr;
6333                     }
6334                 }
6335             }
6336             break;
6337         case WINED3DRTYPE_CUBETEXTURE:
6338             {
6339                 IWineD3DSurface *srcSurface;
6340                 IWineD3DSurface *destSurface;
6341                 WINED3DCUBEMAP_FACES faceType;
6342
6343                 for (i = 0 ; i < levels ; ++i) {
6344                     /* Update each cube face */
6345                     for (faceType = D3DCUBEMAP_FACE_POSITIVE_X; faceType <= D3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
6346                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
6347                         if (WINED3D_OK != hr) {
6348                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6349                         } else {
6350                             TRACE("Got srcSurface %p\n", srcSurface);
6351                         }
6352                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
6353                         if (WINED3D_OK != hr) {
6354                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
6355                         } else {
6356                             TRACE("Got desrSurface %p\n", destSurface);
6357                         }
6358                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
6359                         IWineD3DSurface_Release(srcSurface);
6360                         IWineD3DSurface_Release(destSurface);
6361                         if (WINED3D_OK != hr) {
6362                             WARN("(%p) : Call to update surface failed\n", This);
6363                             return hr;
6364                         }
6365                     }
6366                 }
6367             }
6368             break;
6369 #if 0 /* TODO: Add support for volume textures */
6370         case WINED3DRTYPE_VOLUMETEXTURE:
6371             {
6372                 IWineD3DVolume  srcVolume  = NULL;
6373                 IWineD3DSurface destVolume = NULL;
6374
6375                 for (i = 0 ; i < levels ; ++i) {
6376                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
6377                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
6378                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
6379                     IWineD3DVolume_Release(srcSurface);
6380                     IWineD3DVolume_Release(destSurface);
6381                     if (WINED3D_OK != hr) {
6382                         WARN("(%p) : Call to update volume failed\n", This);
6383                         return hr;
6384                     }
6385                 }
6386             }
6387             break;
6388 #endif
6389         default:
6390             FIXME("(%p) : Unsupported source and destination type\n", This);
6391             hr = WINED3DERR_INVALIDCALL;
6392         }
6393     }
6394
6395     return hr;
6396 }
6397
6398 static HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
6399                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
6400                                                 CONST RECT* pDestRect, WINED3DTEXTUREFILTERTYPE Filter) {
6401     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6402
6403     TRACE("(%p) : stub\n", This);
6404     return WINED3D_OK;
6405 }
6406 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
6407     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6408     /** TODO: remove remove casts to IWineD3DSurfaceImpl *
6409     *  NOTE It may be best to move the code into surface to occomplish this
6410     ****************************************/
6411
6412     WINED3DSURFACE_DESC surfaceDesc;
6413     unsigned int surfaceWidth, surfaceHeight;
6414     glDescriptor *targetGlDescription  = NULL;
6415     glDescriptor *surfaceGlDescription = NULL;
6416     IWineD3DSwapChainImpl *container = NULL;
6417     
6418     IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
6419     IWineD3DSurface_GetGlDesc(pSurface,      &surfaceGlDescription);
6420     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
6421
6422     surfaceDesc.Width  = &surfaceWidth;
6423     surfaceDesc.Height = &surfaceHeight;
6424     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
6425    /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
6426
6427     /* Ok, I may need to setup some kind of active swapchain reference on the device */
6428     IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
6429     ENTER_GL();
6430     /* TODO: opengl Context switching for swapchains etc... */
6431     if (NULL != container  || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
6432         if (NULL != container  && (pRenderTarget == container->backBuffer[0])) {
6433             glReadBuffer(GL_BACK);
6434             vcheckGLcall("glReadBuffer(GL_BACK)");
6435         } else if ((NULL != container  && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
6436             glReadBuffer(GL_FRONT);
6437             vcheckGLcall("glReadBuffer(GL_FRONT)");
6438         } else if (pRenderTarget == This->depthStencilBuffer) {
6439             FIXME("Reading of depthstencil not yet supported\n");
6440         }
6441
6442         glReadPixels(surfaceGlDescription->target,
6443                     surfaceGlDescription->level,
6444                     surfaceWidth,
6445                     surfaceHeight,
6446                     surfaceGlDescription->glFormat,
6447                     surfaceGlDescription->glType,
6448                     (void *)IWineD3DSurface_GetData(pSurface));
6449         vcheckGLcall("glReadPixels(...)");
6450         if(NULL != container ){
6451             IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
6452         }
6453     } else {
6454         IWineD3DBaseTexture *container;
6455         GLenum textureDimensions = GL_TEXTURE_2D;
6456
6457         if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
6458             textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
6459             IWineD3DBaseTexture_Release(container);
6460         }
6461         /* TODO: 2D -> Cube surface coppies etc.. */
6462         if (surfaceGlDescription->target != textureDimensions) {
6463             FIXME("(%p) : Texture dimension mismatch\n", This);
6464         }
6465         glEnable(textureDimensions);
6466         vcheckGLcall("glEnable(GL_TEXTURE_...)");
6467         /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
6468         glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
6469         vcheckGLcall("glBindTexture");
6470         glGetTexImage(surfaceGlDescription->target,
6471                         surfaceGlDescription->level,
6472                         surfaceGlDescription->glFormat,
6473                         surfaceGlDescription->glType,
6474                         (void *)IWineD3DSurface_GetData(pSurface));
6475         glDisable(textureDimensions);
6476         vcheckGLcall("glDisable(GL_TEXTURE_...)");
6477
6478     }
6479     LEAVE_GL();
6480     return WINED3D_OK;
6481 }
6482
6483 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
6484     IWineD3DSwapChain *swapChain;
6485     HRESULT hr;
6486     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
6487     if(hr == WINED3D_OK) {
6488         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
6489                 IWineD3DSwapChain_Release(swapChain);
6490     }
6491     return hr;
6492 }
6493
6494 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
6495     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6496     /* return a sensible default */
6497     *pNumPasses = 1;
6498     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
6499     FIXME("(%p) : stub\n", This);
6500     return WINED3D_OK;
6501 }
6502
6503 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
6504     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6505     int j;
6506     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6507     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6508         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6509         return WINED3DERR_INVALIDCALL;
6510     }
6511     for (j = 0; j < 256; ++j) {
6512         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
6513         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
6514         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
6515         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
6516     }
6517     TRACE("(%p) : returning\n", This);
6518     return WINED3D_OK;
6519 }
6520
6521 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
6522     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6523     int j;
6524     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6525     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6526         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6527         return WINED3DERR_INVALIDCALL;
6528     }
6529     for (j = 0; j < 256; ++j) {
6530         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
6531         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
6532         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
6533         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
6534     }
6535     TRACE("(%p) : returning\n", This);
6536     return WINED3D_OK;
6537 }
6538
6539 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
6540     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6541     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
6542     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
6543         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
6544         return WINED3DERR_INVALIDCALL;
6545     }
6546     /*TODO: stateblocks */
6547     This->currentPalette = PaletteNumber;
6548     TRACE("(%p) : returning\n", This);
6549     return WINED3D_OK;
6550 }
6551
6552 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
6553     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6554     if (PaletteNumber == NULL) {
6555         WARN("(%p) : returning Invalid Call\n", This);
6556         return WINED3DERR_INVALIDCALL;
6557     }
6558     /*TODO: stateblocks */
6559     *PaletteNumber = This->currentPalette;
6560     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
6561     return WINED3D_OK;
6562 }
6563
6564 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
6565     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6566     static BOOL showFixmes = TRUE;
6567     if (showFixmes) {
6568         FIXME("(%p) : stub\n", This);
6569         showFixmes = FALSE;
6570     }
6571
6572     This->softwareVertexProcessing = bSoftware;
6573     return WINED3D_OK;
6574 }
6575
6576
6577 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
6578     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6579     static BOOL showFixmes = TRUE;
6580     if (showFixmes) {
6581         FIXME("(%p) : stub\n", This);
6582         showFixmes = FALSE;
6583     }
6584     return This->softwareVertexProcessing;
6585 }
6586
6587
6588 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
6589     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6590     IWineD3DSwapChain *swapChain;
6591     HRESULT hr;
6592
6593     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
6594
6595     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
6596     if(hr == WINED3D_OK){
6597         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
6598         IWineD3DSwapChain_Release(swapChain);
6599     }else{
6600         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
6601     }
6602     return hr;
6603 }
6604
6605
6606 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
6607     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6608     static BOOL showfixmes = TRUE;
6609     if(nSegments != 0.0f) {
6610         if( showfixmes) {
6611             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
6612             showfixmes = FALSE;
6613         }
6614     }
6615     return WINED3D_OK;
6616 }
6617
6618 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
6619     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6620     static BOOL showfixmes = TRUE;
6621     if( showfixmes) {
6622         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
6623         showfixmes = FALSE;
6624     }
6625     return 0.0f;
6626 }
6627
6628 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
6629     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
6630     /** TODO: remove casts to IWineD3DSurfaceImpl
6631      *       NOTE: move code to surface to accomplish this
6632       ****************************************/
6633     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
6634     int srcWidth, srcHeight;
6635     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
6636     WINED3DFORMAT destFormat, srcFormat;
6637     UINT          destSize;
6638     int destLeft, destTop;
6639     WINED3DPOOL       srcPool, destPool;
6640     int offset    = 0;
6641     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6642     glDescriptor *glDescription = NULL;
6643     GLenum textureDimensions = GL_TEXTURE_2D;
6644     IWineD3DBaseTexture *baseTexture;
6645
6646     WINED3DSURFACE_DESC  winedesc;
6647
6648     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
6649     memset(&winedesc, 0, sizeof(winedesc));
6650     winedesc.Width  = &srcSurfaceWidth;
6651     winedesc.Height = &srcSurfaceHeight;
6652     winedesc.Pool   = &srcPool;
6653     winedesc.Format = &srcFormat;
6654
6655     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6656
6657     winedesc.Width  = &destSurfaceWidth;
6658     winedesc.Height = &destSurfaceHeight;
6659     winedesc.Pool   = &destPool;
6660     winedesc.Format = &destFormat;
6661     winedesc.Size   = &destSize;
6662
6663     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6664
6665     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
6666         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
6667         return WINED3DERR_INVALIDCALL;
6668     }
6669
6670     if (destFormat == WINED3DFMT_UNKNOWN) {
6671         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6672         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6673
6674         /* Get the update surface description */
6675         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6676     }
6677
6678     /* Make sure the surface is loaded and up to date */
6679     IWineD3DSurface_PreLoad(pDestinationSurface);
6680
6681     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
6682
6683     ENTER_GL();
6684
6685     /* this needs to be done in lines if the sourceRect != the sourceWidth */
6686     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
6687     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
6688     destLeft   = pDestPoint  ? pDestPoint->x : 0;
6689     destTop    = pDestPoint  ? pDestPoint->y : 0;
6690
6691
6692     /* This function doesn't support compressed textures
6693     the pitch is just bytesPerPixel * width */
6694     if(srcWidth != srcSurfaceWidth  || (pSourceRect != NULL && pSourceRect->left != 0) ){
6695         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
6696         offset   += pSourceRect->left * pSrcSurface->bytesPerPixel;
6697         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6698     }
6699     /* TODO DXT formats */
6700
6701     if(pSourceRect != NULL && pSourceRect->top != 0){
6702        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
6703     }
6704     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6705     ,This
6706     ,glDescription->level
6707     ,destLeft
6708     ,destTop
6709     ,srcWidth
6710     ,srcHeight
6711     ,glDescription->glFormat
6712     ,glDescription->glType
6713     ,IWineD3DSurface_GetData(pSourceSurface)
6714     );
6715
6716     /* Sanity check */
6717     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
6718
6719         /* need to lock the surface to get the data */
6720         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6721     }
6722
6723     /* TODO: Cube and volume support */
6724     if(rowoffset != 0){
6725         /* not a whole row so we have to do it a line at a time */
6726         int j;
6727
6728         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6729         unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
6730
6731         for(j = destTop ; j < (srcHeight + destTop) ; j++){
6732
6733                 glTexSubImage2D(glDescription->target
6734                     ,glDescription->level
6735                     ,destLeft
6736                     ,j
6737                     ,srcWidth
6738                     ,1
6739                     ,glDescription->glFormat
6740                     ,glDescription->glType
6741                     ,data /* could be quicker using */
6742                 );
6743             data += rowoffset;
6744         }
6745
6746     } else { /* Full width, so just write out the whole texture */
6747
6748         if (WINED3DFMT_DXT1 == destFormat ||
6749             WINED3DFMT_DXT2 == destFormat ||
6750             WINED3DFMT_DXT3 == destFormat ||
6751             WINED3DFMT_DXT4 == destFormat ||
6752             WINED3DFMT_DXT5 == destFormat) {
6753             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
6754                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
6755                     /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6756                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
6757                 } if (destFormat != srcFormat) {
6758                     FIXME("Updating mixed format compressed texture is not curretly support\n");
6759                 } else {
6760                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
6761                                                         glDescription->level,
6762                                                         glDescription->glFormatInternal,
6763                                                         srcWidth,
6764                                                         srcHeight,
6765                                                         0,
6766                                                         destSize,
6767                                                         IWineD3DSurface_GetData(pSourceSurface));
6768                 }
6769             } else {
6770                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6771             }
6772
6773
6774         } else {
6775             if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
6776
6777                 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6778                 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6779                 data returned by GetData non-power2 width/height with hardware non-power2
6780                 pow2Width/height are set to surface width height, repacking isn't needed so it
6781                 doesn't matter which function gets called. */
6782                 glTexSubImage2D(glDescription->target
6783                         ,glDescription->level
6784                         ,destLeft
6785                         ,destTop
6786                         ,srcWidth
6787                         ,srcHeight
6788                         ,glDescription->glFormat
6789                         ,glDescription->glType
6790                         ,IWineD3DSurface_GetData(pSourceSurface)
6791                     );
6792             } else {
6793
6794                 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6795                 glTexSubImage2D(glDescription->target
6796                     ,glDescription->level
6797                     ,destLeft
6798                     ,destTop
6799                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
6800                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
6801                     ,glDescription->glFormat
6802                     ,glDescription->glType
6803                     ,IWineD3DSurface_GetData(pSourceSurface)
6804                 );
6805             }
6806
6807         }
6808      }
6809     checkGLcall("glTexSubImage2D");
6810     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
6811
6812     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6813      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6814      * surface bigger than it needs to be hmm.. */
6815     if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
6816         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
6817         IWineD3DBaseTexture_Release(baseTexture);
6818     }
6819
6820     glDisable(textureDimensions); /* This needs to be managed better.... */
6821     LEAVE_GL();
6822
6823     return WINED3D_OK;
6824 }
6825
6826 /* Used by DirectX 8 */
6827 static HRESULT  WINAPI  IWineD3DDeviceImpl_CopyRects(IWineD3DDevice *iface,
6828                                                 IWineD3DSurface* pSourceSurface,      CONST RECT* pSourceRectsArray, UINT cRects,
6829                                                 IWineD3DSurface* pDestinationSurface, CONST POINT* pDestPointsArray) {
6830
6831     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
6832     HRESULT              hr = WINED3D_OK;
6833     WINED3DFORMAT        srcFormat, destFormat;
6834     UINT                 srcWidth,  destWidth;
6835     UINT                 srcHeight, destHeight;
6836     UINT                 srcSize;
6837     WINED3DSURFACE_DESC  winedesc;
6838
6839     TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
6840           pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
6841
6842
6843     /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6844     memset(&winedesc, 0, sizeof(winedesc));
6845
6846     winedesc.Format = &srcFormat;
6847     winedesc.Width  = &srcWidth;
6848     winedesc.Height = &srcHeight;
6849     winedesc.Size   = &srcSize;
6850     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
6851
6852     winedesc.Format = &destFormat;
6853     winedesc.Width  = &destWidth;
6854     winedesc.Height = &destHeight;
6855     winedesc.Size   = NULL;
6856     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
6857
6858     /* Check that the source and destination formats match */
6859     if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat) {
6860         WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This, pSourceSurface, pDestinationSurface);
6861         return WINED3DERR_INVALIDCALL;
6862     } else if (WINED3DFMT_UNKNOWN == destFormat) {
6863         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
6864         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
6865         destFormat = srcFormat;
6866     }
6867
6868     /* Quick if complete copy ... */
6869     if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
6870
6871         if (srcWidth == destWidth && srcHeight == destHeight) {
6872             WINED3DLOCKED_RECT lrSrc;
6873             WINED3DLOCKED_RECT lrDst;
6874             IWineD3DSurface_LockRect(pSourceSurface,      &lrSrc, NULL, WINED3DLOCK_READONLY);
6875             IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, NULL, 0L);
6876             TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth, srcHeight);
6877
6878             memcpy(lrDst.pBits, lrSrc.pBits, srcSize);
6879
6880             IWineD3DSurface_UnlockRect(pSourceSurface);
6881             IWineD3DSurface_UnlockRect(pDestinationSurface);
6882             TRACE("Unlocked src and dst\n");
6883
6884         } else {
6885
6886             FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6887             hr = WINED3DERR_INVALIDCALL;
6888          }
6889
6890     } else {
6891
6892         if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
6893
6894             int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6895             unsigned int i;
6896
6897             /* Copy rect by rect */
6898             for (i = 0; i < cRects; ++i) {
6899                 CONST RECT*  r = &pSourceRectsArray[i];
6900                 CONST POINT* p = &pDestPointsArray[i];
6901                 int copyperline;
6902                 int j;
6903                 WINED3DLOCKED_RECT lrSrc;
6904                 WINED3DLOCKED_RECT lrDst;
6905                 RECT dest_rect;
6906
6907                 TRACE("Copying rect %d (%d,%d),(%d,%d) -> (%d,%d)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
6908                 if (srcFormat == WINED3DFMT_DXT1) {
6909                     copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6910                 } else {
6911                     copyperline = ((r->right - r->left) * bytesPerPixel);
6912                 }
6913
6914                 IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6915                 dest_rect.left  = p->x;
6916                 dest_rect.top   = p->y;
6917                 dest_rect.right = p->x + (r->right - r->left);
6918                 dest_rect.bottom= p->y + (r->bottom - r->top);
6919                 IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6920                 TRACE("Locked src and dst\n");
6921
6922                 /* Find where to start */
6923                 for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6924                     memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6925                 }
6926                 IWineD3DSurface_UnlockRect(pSourceSurface);
6927                 IWineD3DSurface_UnlockRect(pDestinationSurface);
6928                 TRACE("Unlocked src and dst\n");
6929             }
6930         } else {
6931                 unsigned int i;
6932                 int bytesPerPixel = ((IWineD3DSurfaceImpl *) pSourceSurface)->bytesPerPixel;
6933                 int copyperline;
6934                 int j;
6935                 WINED3DLOCKED_RECT lrSrc;
6936                 WINED3DLOCKED_RECT lrDst;
6937                 RECT dest_rect;
6938                                                                                 
6939                 for(i=0; i < cRects; i++) {
6940                     CONST RECT*  r = &pSourceRectsArray[i];
6941                     
6942                     TRACE("Copying rect %d (%d,%d),(%d,%d) -> (0, 0)\n", i, r->left, r->top, r->right, r->bottom);
6943                     if (srcFormat == WINED3DFMT_DXT1) {
6944                         copyperline = ((r->right - r->left) * bytesPerPixel) / 2; /* DXT1 is half byte per pixel */
6945                     } else {
6946                         copyperline = ((r->right - r->left) * bytesPerPixel);
6947                     }
6948                     IWineD3DSurface_LockRect(pSourceSurface, &lrSrc, r, WINED3DLOCK_READONLY);
6949                     dest_rect.left = 0;
6950                     dest_rect.top = 0;
6951                     dest_rect.right = r->right - r->left;
6952                     dest_rect.bottom= r->bottom - r->top;
6953                     IWineD3DSurface_LockRect(pDestinationSurface, &lrDst, &dest_rect, 0L);
6954                     TRACE("Locked src and dst\n");
6955                     /* Find where to start */
6956                     for (j = 0; j < (r->bottom - r->top - 1); ++j) {
6957                         memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
6958                     }
6959                     IWineD3DSurface_UnlockRect(pSourceSurface);
6960                     IWineD3DSurface_UnlockRect(pDestinationSurface);
6961                     TRACE("Unlocked src and dst\n");
6962                 }
6963         }
6964     }
6965
6966     return hr;
6967 }
6968
6969 /* Implementation details at http://developer.nvidia.com/attach/6494
6970 and
6971 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6972 hmm.. no longer supported use
6973 OpenGL evaluators or  tessellate surfaces within your application.
6974 */
6975
6976 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6977 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
6978     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6979     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
6980     FIXME("(%p) : Stub\n", This);
6981     return WINED3D_OK;
6982
6983 }
6984
6985 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6986 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
6987     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6988     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6989     FIXME("(%p) : Stub\n", This);
6990     return WINED3D_OK;
6991 }
6992
6993 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6994     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6995     TRACE("(%p) Handle(%d)\n", This, Handle);
6996     FIXME("(%p) : Stub\n", This);
6997     return WINED3D_OK;
6998 }
6999
7000 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
7001     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7002     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
7003     DDBLTFX BltFx;
7004     TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
7005
7006     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
7007         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
7008         return WINED3DERR_INVALIDCALL;
7009     }
7010
7011     /* Just forward this to the DirectDraw blitting engine */
7012     memset(&BltFx, 0, sizeof(BltFx));
7013     BltFx.dwSize = sizeof(BltFx);
7014     BltFx.u5.dwFillColor = color;
7015     return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
7016 }
7017
7018 /* rendertarget and deptth stencil functions */
7019 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
7020     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7021
7022     /* FIXME: Implelent RenderTargetIndex >0 */
7023     if(RenderTargetIndex > 0)
7024         FIXME("(%p) : RenderTargetIndex %d >0 not currently supported\n", This, RenderTargetIndex);
7025
7026     *ppRenderTarget = This->renderTarget;
7027     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
7028     /* Note inc ref on returned surface */
7029     if(*ppRenderTarget != NULL)
7030         IWineD3DSurface_AddRef(*ppRenderTarget);
7031     return WINED3D_OK;
7032 }
7033
7034 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
7035     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7036     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
7037     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
7038     IWineD3DSwapChainImpl *Swapchain;
7039     HRESULT hr;
7040
7041     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
7042
7043     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
7044     if(hr != WINED3D_OK) {
7045         ERR("Can't get the swapchain\n");
7046         return hr;
7047     }
7048
7049     /* Make sure to release the swapchain */
7050     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
7051
7052     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
7053         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7054         return WINED3DERR_INVALIDCALL;
7055     }
7056     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
7057         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
7058         return WINED3DERR_INVALIDCALL;
7059     }
7060
7061     if(Swapchain->frontBuffer != Front) {
7062         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
7063
7064         if(Swapchain->frontBuffer)
7065             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
7066         Swapchain->frontBuffer = Front;
7067
7068         if(Swapchain->frontBuffer) {
7069             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
7070         }
7071     }
7072
7073     if(Back && !Swapchain->backBuffer) {
7074         /* We need memory for the back buffer array - only one back buffer this way */
7075         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
7076         if(!Swapchain->backBuffer) {
7077             ERR("Out of memory\n");
7078             return E_OUTOFMEMORY;
7079         }
7080     }
7081
7082     if(Swapchain->backBuffer[0] != Back) {
7083         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
7084         ENTER_GL();
7085         if(!Swapchain->backBuffer[0]) {
7086             /* GL was told to draw to the front buffer at creation,
7087              * undo that
7088              */
7089             glDrawBuffer(GL_BACK);
7090             checkGLcall("glDrawBuffer(GL_BACK)");
7091             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
7092             Swapchain->presentParms.BackBufferCount = 1;
7093         } else if (!Back) {
7094             /* That makes problems - disable for now */
7095             /* glDrawBuffer(GL_FRONT); */
7096             checkGLcall("glDrawBuffer(GL_FRONT)");
7097             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
7098             Swapchain->presentParms.BackBufferCount = 0;
7099         }
7100         LEAVE_GL();
7101
7102         if(Swapchain->backBuffer[0])
7103             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
7104         Swapchain->backBuffer[0] = Back;
7105
7106         if(Swapchain->backBuffer[0]) {
7107             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
7108         } else {
7109             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
7110         }
7111
7112     }
7113
7114     return WINED3D_OK;
7115 }
7116
7117 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
7118     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7119     *ppZStencilSurface = This->depthStencilBuffer;
7120     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
7121
7122     if(*ppZStencilSurface != NULL) {
7123         /* Note inc ref on returned surface */
7124         IWineD3DSurface_AddRef(*ppZStencilSurface);
7125     }
7126     return WINED3D_OK;
7127 }
7128
7129 /* internal static helper functions */
7130 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7131                                                 IWineD3DSurface *RenderSurface);
7132
7133 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
7134     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7135     HRESULT  hr = WINED3D_OK;
7136     WINED3DVIEWPORT viewport;
7137
7138     TRACE("(%p) Swapping rendertarget\n",This);
7139     if (RenderTargetIndex > 0) {
7140         FIXME("(%p) Render targets other than the first are not supported\n",This);
7141         RenderTargetIndex = 0;
7142     }
7143
7144     /* MSDN says that null disables the render target
7145     but a device must always be associated with a render target
7146     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
7147
7148     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
7149     for more details
7150     */
7151     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
7152         FIXME("Trying to set render target 0 to NULL\n");
7153         return WINED3DERR_INVALIDCALL;
7154     }
7155     /* TODO: replace Impl* usage with interface usage */
7156     if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
7157         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);
7158         return WINED3DERR_INVALIDCALL;
7159     }
7160     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
7161      *        builds, but I think wine counts as a 'debug' build for now.
7162       ******************************/
7163     /* If we are trying to set what we already have, don't bother */
7164     if (pRenderTarget == This->renderTarget) {
7165         TRACE("Trying to do a NOP SetRenderTarget operation\n");
7166     } else {
7167         /* Otherwise, set the render target up */
7168
7169         if (!This->sceneEnded) {
7170             IWineD3DDevice_EndScene(iface);
7171         }
7172         TRACE("clearing renderer\n");
7173         /* IWineD3DDeviceImpl_CleanRender(iface); */
7174         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7175         depending on the renter target implementation being used.
7176         A shared context implementation will share all buffers between all rendertargets (including swapchains),
7177         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7178         stencil buffer and incure an extra memory overhead */
7179         hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
7180     }
7181
7182     if (SUCCEEDED(hr)) {
7183         /* Finally, reset the viewport as the MSDN states. */
7184         /* TODO: Replace impl usage */
7185         viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
7186         viewport.Width  = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
7187         viewport.X      = 0;
7188         viewport.Y      = 0;
7189         viewport.MaxZ   = 1.0f;
7190         viewport.MinZ   = 0.0f;
7191         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
7192     } else {
7193         FIXME("Unknown error setting the render target\n");
7194     }
7195     This->sceneEnded = FALSE;
7196     return hr;
7197 }
7198
7199 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
7200     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7201     HRESULT  hr = WINED3D_OK;
7202     IWineD3DSurface *tmp;
7203
7204     TRACE("(%p) Swapping z-buffer\n",This);
7205
7206     if (pNewZStencil == This->stencilBufferTarget) {
7207         TRACE("Trying to do a NOP SetRenderTarget operation\n");
7208     } else {
7209         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
7210         * depending on the renter target implementation being used.
7211         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
7212         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
7213         * stencil buffer and incure an extra memory overhead
7214          ******************************************************/
7215
7216
7217         tmp = This->stencilBufferTarget;
7218         This->stencilBufferTarget = pNewZStencil;
7219         /* should we be calling the parent or the wined3d surface? */
7220         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
7221         if (NULL != tmp) IWineD3DSurface_Release(tmp);
7222         hr = WINED3D_OK;
7223         /** TODO: glEnable/glDisable on depth/stencil    depending on
7224          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
7225           **********************************************************/
7226     }
7227
7228     return hr;
7229 }
7230
7231
7232 #ifdef GL_VERSION_1_3
7233 /* Internal functions not in DirectX */
7234  /** TODO: move this off to the opengl context manager
7235  *(the swapchain doesn't need to know anything about offscreen rendering!)
7236   ****************************************************/
7237
7238 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
7239 {
7240     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7241
7242     TRACE("(%p), %p\n", This, swapchain);
7243
7244     if (swapchain->win != swapchain->drawable) {
7245         /* Set everything back the way it ws */
7246         swapchain->render_ctx = swapchain->glCtx;
7247         swapchain->drawable   = swapchain->win;
7248     }
7249     return WINED3D_OK;
7250 }
7251
7252 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
7253 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
7254     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7255     int i;
7256     unsigned int width;
7257     unsigned int height;
7258     WINED3DFORMAT format;
7259     WINED3DSURFACE_DESC surfaceDesc;
7260     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
7261     surfaceDesc.Width  = &width;
7262     surfaceDesc.Height = &height;
7263     surfaceDesc.Format = &format;
7264     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
7265     *context = NULL;
7266     /* I need a get width/height function (and should do something with the format) */
7267     for (i = 0; i < CONTEXT_CACHE; ++i) {
7268         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
7269         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
7270         the pSurface can be set to 0 allowing it to be reused from cache **/
7271         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
7272           && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
7273             *context = &This->contextCache[i];
7274             break;
7275         }
7276         if (This->contextCache[i].Width == 0) {
7277             This->contextCache[i].pSurface = pSurface;
7278             This->contextCache[i].Width    = width;
7279             This->contextCache[i].Height   = height;
7280             *context = &This->contextCache[i];
7281             break;
7282         }
7283     }
7284     if (i == CONTEXT_CACHE) {
7285         int minUsage = 0x7FFFFFFF; /* MAX_INT */
7286         glContext *dropContext = 0;
7287         for (i = 0; i < CONTEXT_CACHE; i++) {
7288             if (This->contextCache[i].usedcount < minUsage) {
7289                 dropContext = &This->contextCache[i];
7290                 minUsage = This->contextCache[i].usedcount;
7291             }
7292         }
7293         /* clean up the context (this doesn't work for ATI at the moment */
7294 #if 0
7295         glXDestroyContext(swapchain->display, dropContext->context);
7296         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
7297 #endif
7298         FIXME("Leak\n");
7299         dropContext->Width = 0;
7300         dropContext->pSurface = pSurface;
7301         *context = dropContext;
7302     } else {
7303         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
7304           for (i = 0; i < CONTEXT_CACHE; i++) {
7305              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
7306           }
7307         }
7308     }
7309     if (*context != NULL)
7310         return WINED3D_OK;
7311     else
7312         return E_OUTOFMEMORY;
7313 }
7314 #endif
7315
7316 /* Reapply the device stateblock */
7317 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
7318
7319     BOOL oldRecording;  
7320     IWineD3DStateBlockImpl *oldUpdateStateBlock;
7321
7322     /* Disable recording */
7323     oldUpdateStateBlock = This->updateStateBlock;
7324     oldRecording= This->isRecordingState;
7325     This->isRecordingState = FALSE;
7326     This->updateStateBlock = This->stateBlock;
7327
7328     /* Reapply the state block */ 
7329     IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
7330
7331     /* Restore recording */
7332     This->isRecordingState = oldRecording;
7333     This->updateStateBlock = oldUpdateStateBlock;
7334 }
7335
7336 /* Set the device to render to a texture, or not.
7337  * This involves changing renderUpsideDown */
7338
7339 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
7340
7341     DWORD cullMode;
7342     BOOL oldRecording;
7343     IWineD3DStateBlockImpl *oldUpdateStateBlock;
7344
7345     /* Disable recording */
7346     oldUpdateStateBlock = This->updateStateBlock;
7347     oldRecording= This->isRecordingState;
7348     This->isRecordingState = FALSE;
7349     This->updateStateBlock = This->stateBlock;
7350
7351     /* Set upside-down rendering, and update the cull mode */
7352     /* The surface must be rendered upside down to cancel the flip produced by glCopyTexImage */
7353     This->renderUpsideDown = isTexture;
7354     This->last_was_rhw = FALSE;
7355     This->proj_valid = FALSE;
7356     IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
7357     IWineD3DDevice_SetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, cullMode);
7358
7359     /* Restore recording */
7360     This->isRecordingState = oldRecording;
7361     This->updateStateBlock = oldUpdateStateBlock;
7362 }
7363
7364 /* Returns an array of compatible FBconfig(s).
7365  * The array must be freed with XFree. Requires ENTER_GL() */
7366
7367 static GLXFBConfig* device_find_fbconfigs(
7368     IWineD3DDeviceImpl* This,
7369     IWineD3DSwapChainImpl* implicitSwapchainImpl,
7370     IWineD3DSurface* RenderSurface) {
7371
7372     GLXFBConfig* cfgs = NULL;
7373     int nCfgs = 0;
7374     int attribs[256];
7375     int nAttribs = 0;
7376
7377     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
7378     D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
7379     D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
7380
7381     /**TODO:
7382         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off, 
7383         it StencilSurface != NULL && zBufferTarget == NULL switch it on
7384     */
7385
7386 #define PUSH1(att)        attribs[nAttribs++] = (att);
7387 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
7388
7389     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
7390
7391     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
7392     PUSH2(GLX_X_RENDERABLE,  TRUE);
7393     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
7394     TRACE("calling makeglcfg\n");
7395     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
7396     PUSH1(None);
7397     TRACE("calling chooseFGConfig\n");
7398     cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7399                              DefaultScreen(implicitSwapchainImpl->display),
7400                              attribs, &nCfgs);
7401     if (cfgs == NULL) {
7402         /* OK we didn't find the exact config, so use any reasonable match */
7403         /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
7404            why we failed. */
7405         static BOOL show_message = TRUE;
7406         if (show_message) {
7407             ERR("Failed to find exact match, finding alternative but you may "
7408                 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
7409             show_message = FALSE;
7410         }
7411         nAttribs = 0;
7412         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
7413         /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
7414         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
7415         PUSH2(GLX_DOUBLEBUFFER, FALSE);
7416         TRACE("calling makeglcfg\n");
7417         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
7418         PUSH1(None);
7419         cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
7420                                  DefaultScreen(implicitSwapchainImpl->display),
7421                                  attribs, &nCfgs);
7422     }
7423                                                                                                                                                                       
7424     if (cfgs == NULL) {
7425         ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
7426             BackBufferFormat, debug_d3dformat(BackBufferFormat),
7427             StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
7428     } else {
7429 #ifdef EXTRA_TRACES
7430         int i;
7431         for (i = 0; i < nCfgs; ++i) {
7432             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
7433             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
7434             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
7435         }
7436         if (NULL != This->renderTarget) {
7437             glFlush();
7438             vcheckGLcall("glFlush");
7439             /** This is only useful if the old render target was a swapchain,
7440             * we need to supercede this with a function that displays
7441             * the current buffer on the screen. This is easy to do in glx1.3 but
7442             * we need to do copy-write pixels in glx 1.2.
7443             ************************************************/
7444             glXSwapBuffers(implicitSwapChainImpl->display,
7445                            implicitSwapChainImpl->drawable);
7446             printf("Hit Enter to get next frame ...\n");
7447             getchar();
7448         }
7449 #endif
7450     }
7451 #undef PUSH1
7452 #undef PUSH2
7453
7454    return cfgs;
7455 }
7456
7457 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
7458 * the functionality needs splitting up so that we don't do more than we should do.
7459 * this only seems to impact performance a little.
7460  ******************************/
7461 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
7462                                                IWineD3DSurface *RenderSurface) {
7463
7464     /**
7465     * Currently only active for GLX >= 1.3
7466     * for others versions we'll have to use GLXPixmaps
7467     *
7468     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
7469     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
7470     * so only check OpenGL version
7471     * ..........................
7472     * I don't believe that it is a problem with NVidia headers,
7473     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
7474     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
7475     * ATI Note:
7476     * Your application will report GLX version 1.2 on glXQueryVersion.
7477     * However, it is safe to call the GLX 1.3 functions as described below.
7478     */
7479 #if defined(GL_VERSION_1_3)
7480
7481     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7482     GLXFBConfig* cfgs = NULL;
7483     IWineD3DSwapChain     *currentSwapchain;
7484     IWineD3DSwapChainImpl *currentSwapchainImpl;
7485     IWineD3DSwapChain     *implicitSwapchain;
7486     IWineD3DSwapChainImpl *implicitSwapchainImpl;
7487     IWineD3DSwapChain     *renderSurfaceSwapchain;
7488     IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
7489
7490     /* Obtain a reference to the device implicit swapchain,
7491      * the swapchain of the current render target,
7492      * and the swapchain of the new render target.
7493      * Fallback to device implicit swapchain if the current render target doesn't have one */
7494     IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
7495     IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
7496     IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain);
7497     if (currentSwapchain == NULL)
7498         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
7499
7500     currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
7501     implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
7502     renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
7503
7504     ENTER_GL();
7505
7506     /**
7507     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
7508     *  renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
7509      **********************************************************************/
7510     if (renderSurfaceSwapchain != NULL) {
7511
7512         /* We also need to make sure that the lights &co are also in the context of the swapchains */
7513         /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
7514         TRACE("making swapchain active\n");
7515         if (RenderSurface != This->renderTarget) {
7516             BOOL backbuf = FALSE;
7517             int i;
7518
7519             for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
7520                 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
7521                     backbuf = TRUE;
7522                     break;
7523                 }
7524             }
7525
7526             if (backbuf) {
7527             } else {
7528                 /* This could be flagged so that some operations work directly with the front buffer */
7529                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
7530             }
7531             if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
7532                                renderSurfaceSwapchainImpl->win,
7533                                renderSurfaceSwapchainImpl->glCtx) == False) {
7534
7535                 TRACE("Error in setting current context: context %p drawable %ld !\n",
7536                        implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
7537             }
7538             checkGLcall("glXMakeContextCurrent");
7539
7540             /* Clean up the old context */
7541             IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7542
7543             /* Reapply the stateblock, and set the device not to render to texture */
7544             device_reapply_stateblock(This);
7545             device_render_to_texture(This, FALSE);
7546         }
7547
7548     /* Offscreen rendering: PBuffers (currently disabled).
7549      * Also note that this path is never reached if FBOs are supported */
7550     } else if (pbuffer_support &&
7551                (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
7552
7553         /** ********************************************************************
7554         * This is a quickly hacked out implementation of offscreen textures.
7555         * It will work in most cases but there may be problems if the client
7556         * modifies the texture directly, or expects the contents of the rendertarget
7557         * to be persistent.
7558         *
7559         * There are some real speed vs compatibility issues here:
7560         *    we should really use a new context for every texture, but that eats ram.
7561         *    we should also be restoring the texture to the pbuffer but that eats CPU
7562         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
7563         *    but if this means reusing the display backbuffer then we need to make sure that
7564         *    states are correctly preserved.
7565         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
7566         * and gain a good performance increase at the cost of compatibility.
7567         * I would suggest that, when this is the case, a user configurable flag be made
7568         * available, allowing the user to choose the best emulated experience for them.
7569          *********************************************************************/
7570
7571         XVisualInfo *visinfo;
7572         glContext   *newContext;
7573
7574         /* Here were using a shared context model */
7575         if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
7576             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7577         }
7578
7579         /* If the context doesn't exist then create a new one */
7580         /* TODO: This should really be part of findGlContext */
7581         if (NULL == newContext->context) {
7582
7583             int attribs[256];
7584             int nAttribs = 0;
7585
7586             TRACE("making new buffer\n");
7587             attribs[nAttribs++] = GLX_PBUFFER_WIDTH; 
7588             attribs[nAttribs++] = newContext->Width;
7589             attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
7590             attribs[nAttribs++] = newContext->Height;
7591             attribs[nAttribs++] = None;
7592
7593             newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
7594
7595             /** ****************************************
7596             *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
7597             *they note:
7598             *   In future releases, we may provide the calls glXCreateNewContext,
7599             *   glXQueryDrawable and glXMakeContextCurrent.
7600             *    so until then we have to use glXGetVisualFromFBConfig &co..
7601             ********************************************/
7602
7603             visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
7604             if (!visinfo) {
7605                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7606             } else {
7607                 newContext->context = glXCreateContext(
7608                     implicitSwapchainImpl->display, visinfo,
7609                     implicitSwapchainImpl->glCtx, GL_TRUE);
7610
7611                 XFree(visinfo);
7612             }
7613         }
7614         if (NULL == newContext || NULL == newContext->context) {
7615             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
7616         } else {
7617             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7618             if (glXMakeCurrent(implicitSwapchainImpl->display,
7619                 newContext->drawable, newContext->context) == False) {
7620
7621                 TRACE("Error in setting current context: context %p drawable %ld\n",
7622                     newContext->context, newContext->drawable);
7623             }
7624             checkGLcall("glXMakeContextCurrent");
7625
7626             /* Clean up the old context */
7627             IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
7628
7629             /* Reapply stateblock, and set device to render to a texture */
7630             device_reapply_stateblock(This);
7631             device_render_to_texture(This, TRUE);
7632
7633             /* Set the current context of the swapchain to the new context */
7634             implicitSwapchainImpl->drawable   = newContext->drawable;
7635             implicitSwapchainImpl->render_ctx = newContext->context;
7636         }
7637     } else {
7638         /* Same context, but update renderUpsideDown and cull mode */
7639         device_render_to_texture(This, TRUE);
7640     }
7641
7642     /* Replace the render target */
7643     if (This->renderTarget != RenderSurface) {
7644         IWineD3DSurface_Release(This->renderTarget);
7645         This->renderTarget = RenderSurface;
7646         IWineD3DSurface_AddRef(RenderSurface);
7647     }
7648
7649     if (cfgs != NULL)                   XFree(cfgs);
7650     if (implicitSwapchain != NULL)       IWineD3DSwapChain_Release(implicitSwapchain);
7651     if (currentSwapchain != NULL)       IWineD3DSwapChain_Release(currentSwapchain);
7652     if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
7653     LEAVE_GL();
7654 #endif
7655     return WINED3D_OK;
7656 }
7657
7658 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
7659                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
7660     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7661     /* TODO: the use of Impl is deprecated. */
7662     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
7663
7664     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
7665
7666     /* some basic validation checks */
7667     if(This->cursorTexture) {
7668         ENTER_GL();
7669         glDeleteTextures(1, &This->cursorTexture);
7670         LEAVE_GL();
7671         This->cursorTexture = 0;
7672     }
7673
7674     if(pCursorBitmap) {
7675         /* MSDN: Cursor must be A8R8G8B8 */
7676         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
7677             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
7678             return WINED3DERR_INVALIDCALL;
7679         }
7680
7681         /* MSDN: Cursor must be smaller than the display mode */
7682         if(pSur->currentDesc.Width > This->ddraw_width ||
7683            pSur->currentDesc.Height > This->ddraw_height) {
7684             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);
7685             return WINED3DERR_INVALIDCALL;
7686         }
7687
7688         /* TODO: MSDN: Cursor sizes must be a power of 2 */
7689         /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
7690          * Texture and Blitting code to draw the cursor
7691          */
7692         pSur->Flags |= SFLAG_FORCELOAD;
7693         IWineD3DSurface_PreLoad(pCursorBitmap);
7694         pSur->Flags &= ~SFLAG_FORCELOAD;
7695         /* Do not store the surface's pointer because the application may release
7696          * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
7697          * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
7698          */
7699         This->cursorTexture = pSur->glDescription.textureName;
7700         This->cursorWidth = pSur->currentDesc.Width;
7701         This->cursorHeight = pSur->currentDesc.Height;
7702         pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
7703     }
7704
7705     This->xHotSpot = XHotSpot;
7706     This->yHotSpot = YHotSpot;
7707     return WINED3D_OK;
7708 }
7709
7710 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
7711     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7712     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
7713
7714     This->xScreenSpace = XScreenSpace;
7715     This->yScreenSpace = YScreenSpace;
7716
7717     return;
7718
7719 }
7720
7721 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
7722     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7723     BOOL oldVisible = This->bCursorVisible;
7724     TRACE("(%p) : visible(%d)\n", This, bShow);
7725
7726     if(This->cursorTexture)
7727         This->bCursorVisible = bShow;
7728
7729     return oldVisible;
7730 }
7731
7732 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
7733     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7734     TRACE("(%p) : state (%u)\n", This, This->state);
7735     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7736     switch (This->state) {
7737     case WINED3D_OK:
7738         return WINED3D_OK;
7739     case WINED3DERR_DEVICELOST:
7740         {
7741             ResourceList *resourceList  = This->resources;
7742             while (NULL != resourceList) {
7743                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7744                 return WINED3DERR_DEVICENOTRESET;
7745                 resourceList = resourceList->next;
7746             }
7747             return WINED3DERR_DEVICELOST;
7748         }
7749     case WINED3DERR_DRIVERINTERNALERROR:
7750         return WINED3DERR_DRIVERINTERNALERROR;
7751     }
7752
7753     /* Unknown state */
7754     return WINED3DERR_DRIVERINTERNALERROR;
7755 }
7756
7757
7758 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
7759     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7760     /** FIXME: Resource tracking needs to be done,
7761     * The closes we can do to this is set the priorities of all managed textures low
7762     * and then reset them.
7763      ***********************************************************/
7764     FIXME("(%p) : stub\n", This);
7765     return WINED3D_OK;
7766 }
7767
7768 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7769     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7770     /** FIXME: Resource trascking needs to be done.
7771     * in effect this pulls all non only default
7772     * textures out of video memory and deletes all glTextures (glDeleteTextures)
7773     * and should clear down the context and set it up according to pPresentationParameters
7774      ***********************************************************/
7775     FIXME("(%p) : stub\n", This);
7776     return WINED3D_OK;
7777 }
7778
7779 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7780     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7781     /** FIXME: always true at the moment **/
7782     if(!bEnableDialogs) {
7783         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7784     }
7785     return WINED3D_OK;
7786 }
7787
7788
7789 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7790     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7791     TRACE("(%p) : pParameters %p\n", This, pParameters);
7792
7793     *pParameters = This->createParms;
7794     return WINED3D_OK;
7795 }
7796
7797 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7798     IWineD3DSwapChain *swapchain;
7799     HRESULT hrc = WINED3D_OK;
7800
7801     TRACE("Relaying  to swapchain\n");
7802
7803     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7804         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7805         IWineD3DSwapChain_Release(swapchain);
7806     }
7807     return;
7808 }
7809
7810 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7811     IWineD3DSwapChain *swapchain;
7812     HRESULT hrc = WINED3D_OK;
7813
7814     TRACE("Relaying  to swapchain\n");
7815
7816     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
7817         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7818         IWineD3DSwapChain_Release(swapchain);
7819     }
7820     return;
7821 }
7822
7823
7824 /** ********************************************************
7825 *   Notification functions
7826 ** ********************************************************/
7827 /** This function must be called in the release of a resource when ref == 0,
7828 * the contents of resource must still be correct,
7829 * any handels to other resource held by the caller must be closed
7830 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7831  *****************************************************/
7832 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7833     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7834     ResourceList* resourceList;
7835
7836     TRACE("(%p) : resource %p\n", This, resource);
7837 #if 0
7838     EnterCriticalSection(&resourceStoreCriticalSection);
7839 #endif
7840     /* add a new texture to the frot of the linked list */
7841     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
7842     resourceList->resource = resource;
7843
7844     /* Get the old head */
7845     resourceList->next = This->resources;
7846
7847     This->resources = resourceList;
7848     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
7849
7850 #if 0
7851     LeaveCriticalSection(&resourceStoreCriticalSection);
7852 #endif
7853     return;
7854 }
7855
7856 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7857     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7858     ResourceList* resourceList = NULL;
7859     ResourceList* previousResourceList = NULL;
7860     
7861     TRACE("(%p) : resource %p\n", This, resource);
7862
7863 #if 0
7864     EnterCriticalSection(&resourceStoreCriticalSection);
7865 #endif
7866     resourceList = This->resources;
7867
7868     while (resourceList != NULL) {
7869         if(resourceList->resource == resource) break;
7870         previousResourceList = resourceList;
7871         resourceList = resourceList->next;
7872     }
7873
7874     if (resourceList == NULL) {
7875         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
7876 #if 0
7877         LeaveCriticalSection(&resourceStoreCriticalSection);
7878 #endif
7879         return;
7880     } else {
7881             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
7882     }
7883     /* make sure we don't leave a hole in the list */
7884     if (previousResourceList != NULL) {
7885         previousResourceList->next = resourceList->next;
7886     } else {
7887         This->resources = resourceList->next;
7888     }
7889
7890 #if 0
7891     LeaveCriticalSection(&resourceStoreCriticalSection);
7892 #endif
7893     return;
7894 }
7895
7896
7897 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7898     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7899     int counter;
7900
7901     TRACE("(%p) : resource %p\n", This, resource);
7902     switch(IWineD3DResource_GetType(resource)){
7903         case WINED3DRTYPE_SURFACE:
7904         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
7905         break;
7906         case WINED3DRTYPE_TEXTURE:
7907         case WINED3DRTYPE_CUBETEXTURE:
7908         case WINED3DRTYPE_VOLUMETEXTURE:
7909                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
7910                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7911                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7912                         This->stateBlock->textures[counter] = NULL;
7913                     }
7914                     if (This->updateStateBlock != This->stateBlock ){
7915                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7916                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7917                             This->updateStateBlock->textures[counter] = NULL;
7918                         }
7919                     }
7920                 }
7921         break;
7922         case WINED3DRTYPE_VOLUME:
7923         /* TODO: nothing really? */
7924         break;
7925         case WINED3DRTYPE_VERTEXBUFFER:
7926         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7927         {
7928             int streamNumber;
7929             TRACE("Cleaning up stream pointers\n");
7930
7931             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7932                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7933                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7934                 */
7935                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7936                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7937                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7938                         This->updateStateBlock->streamSource[streamNumber] = 0;
7939                         /* Set changed flag? */
7940                     }
7941                 }
7942                 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) */
7943                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7944                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7945                         This->stateBlock->streamSource[streamNumber] = 0;
7946                     }
7947                 }
7948 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7949                  else { /* This shouldn't happen */
7950                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7951                 }
7952 #endif
7953
7954             }
7955         }
7956         break;
7957         case WINED3DRTYPE_INDEXBUFFER:
7958         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7959         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7960             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7961                 This->updateStateBlock->pIndexData =  NULL;
7962             }
7963         }
7964         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7965             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7966                 This->stateBlock->pIndexData =  NULL;
7967             }
7968         }
7969
7970         break;
7971         default:
7972         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7973         break;
7974     }
7975
7976
7977     /* Remove the resoruce from the resourceStore */
7978     IWineD3DDeviceImpl_RemoveResource(iface, resource);
7979
7980     TRACE("Resource released\n");
7981
7982 }
7983
7984 /**********************************************************
7985  * IWineD3DDevice VTbl follows
7986  **********************************************************/
7987
7988 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7989 {
7990     /*** IUnknown methods ***/
7991     IWineD3DDeviceImpl_QueryInterface,
7992     IWineD3DDeviceImpl_AddRef,
7993     IWineD3DDeviceImpl_Release,
7994     /*** IWineD3DDevice methods ***/
7995     IWineD3DDeviceImpl_GetParent,
7996     /*** Creation methods**/
7997     IWineD3DDeviceImpl_CreateVertexBuffer,
7998     IWineD3DDeviceImpl_CreateIndexBuffer,
7999     IWineD3DDeviceImpl_CreateStateBlock,
8000     IWineD3DDeviceImpl_CreateSurface,
8001     IWineD3DDeviceImpl_CreateTexture,
8002     IWineD3DDeviceImpl_CreateVolumeTexture,
8003     IWineD3DDeviceImpl_CreateVolume,
8004     IWineD3DDeviceImpl_CreateCubeTexture,
8005     IWineD3DDeviceImpl_CreateQuery,
8006     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
8007     IWineD3DDeviceImpl_CreateVertexDeclaration,
8008     IWineD3DDeviceImpl_CreateVertexShader,
8009     IWineD3DDeviceImpl_CreatePixelShader,
8010     IWineD3DDeviceImpl_CreatePalette,
8011     /*** Odd functions **/
8012     IWineD3DDeviceImpl_Init3D,
8013     IWineD3DDeviceImpl_Uninit3D,
8014     IWineD3DDeviceImpl_SetFullscreen,
8015     IWineD3DDeviceImpl_EnumDisplayModes,
8016     IWineD3DDeviceImpl_EvictManagedResources,
8017     IWineD3DDeviceImpl_GetAvailableTextureMem,
8018     IWineD3DDeviceImpl_GetBackBuffer,
8019     IWineD3DDeviceImpl_GetCreationParameters,
8020     IWineD3DDeviceImpl_GetDeviceCaps,
8021     IWineD3DDeviceImpl_GetDirect3D,
8022     IWineD3DDeviceImpl_GetDisplayMode,
8023     IWineD3DDeviceImpl_SetDisplayMode,
8024     IWineD3DDeviceImpl_GetHWND,
8025     IWineD3DDeviceImpl_SetHWND,
8026     IWineD3DDeviceImpl_GetNumberOfSwapChains,
8027     IWineD3DDeviceImpl_GetRasterStatus,
8028     IWineD3DDeviceImpl_GetSwapChain,
8029     IWineD3DDeviceImpl_Reset,
8030     IWineD3DDeviceImpl_SetDialogBoxMode,
8031     IWineD3DDeviceImpl_SetCursorProperties,
8032     IWineD3DDeviceImpl_SetCursorPosition,
8033     IWineD3DDeviceImpl_ShowCursor,
8034     IWineD3DDeviceImpl_TestCooperativeLevel,
8035     /*** Getters and setters **/
8036     IWineD3DDeviceImpl_SetClipPlane,
8037     IWineD3DDeviceImpl_GetClipPlane,
8038     IWineD3DDeviceImpl_SetClipStatus,
8039     IWineD3DDeviceImpl_GetClipStatus,
8040     IWineD3DDeviceImpl_SetCurrentTexturePalette,
8041     IWineD3DDeviceImpl_GetCurrentTexturePalette,
8042     IWineD3DDeviceImpl_SetDepthStencilSurface,
8043     IWineD3DDeviceImpl_GetDepthStencilSurface,
8044     IWineD3DDeviceImpl_SetFVF,
8045     IWineD3DDeviceImpl_GetFVF,
8046     IWineD3DDeviceImpl_SetGammaRamp,
8047     IWineD3DDeviceImpl_GetGammaRamp,
8048     IWineD3DDeviceImpl_SetIndices,
8049     IWineD3DDeviceImpl_GetIndices,
8050     IWineD3DDeviceImpl_SetLight,
8051     IWineD3DDeviceImpl_GetLight,
8052     IWineD3DDeviceImpl_SetLightEnable,
8053     IWineD3DDeviceImpl_GetLightEnable,
8054     IWineD3DDeviceImpl_SetMaterial,
8055     IWineD3DDeviceImpl_GetMaterial,
8056     IWineD3DDeviceImpl_SetNPatchMode,
8057     IWineD3DDeviceImpl_GetNPatchMode,
8058     IWineD3DDeviceImpl_SetPaletteEntries,
8059     IWineD3DDeviceImpl_GetPaletteEntries,
8060     IWineD3DDeviceImpl_SetPixelShader,
8061     IWineD3DDeviceImpl_GetPixelShader,
8062     IWineD3DDeviceImpl_SetPixelShaderConstantB,
8063     IWineD3DDeviceImpl_GetPixelShaderConstantB,
8064     IWineD3DDeviceImpl_SetPixelShaderConstantI,
8065     IWineD3DDeviceImpl_GetPixelShaderConstantI,
8066     IWineD3DDeviceImpl_SetPixelShaderConstantF,
8067     IWineD3DDeviceImpl_GetPixelShaderConstantF,
8068     IWineD3DDeviceImpl_SetRenderState,
8069     IWineD3DDeviceImpl_GetRenderState,
8070     IWineD3DDeviceImpl_SetRenderTarget,
8071     IWineD3DDeviceImpl_GetRenderTarget,
8072     IWineD3DDeviceImpl_SetFrontBackBuffers,
8073     IWineD3DDeviceImpl_SetSamplerState,
8074     IWineD3DDeviceImpl_GetSamplerState,
8075     IWineD3DDeviceImpl_SetScissorRect,
8076     IWineD3DDeviceImpl_GetScissorRect,
8077     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
8078     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
8079     IWineD3DDeviceImpl_SetStreamSource,
8080     IWineD3DDeviceImpl_GetStreamSource,
8081     IWineD3DDeviceImpl_SetStreamSourceFreq,
8082     IWineD3DDeviceImpl_GetStreamSourceFreq,
8083     IWineD3DDeviceImpl_SetTexture,
8084     IWineD3DDeviceImpl_GetTexture,
8085     IWineD3DDeviceImpl_SetTextureStageState,
8086     IWineD3DDeviceImpl_GetTextureStageState,
8087     IWineD3DDeviceImpl_SetTransform,
8088     IWineD3DDeviceImpl_GetTransform,
8089     IWineD3DDeviceImpl_SetVertexDeclaration,
8090     IWineD3DDeviceImpl_GetVertexDeclaration,
8091     IWineD3DDeviceImpl_SetVertexShader,
8092     IWineD3DDeviceImpl_GetVertexShader,
8093     IWineD3DDeviceImpl_SetVertexShaderConstantB,
8094     IWineD3DDeviceImpl_GetVertexShaderConstantB,
8095     IWineD3DDeviceImpl_SetVertexShaderConstantI,
8096     IWineD3DDeviceImpl_GetVertexShaderConstantI,
8097     IWineD3DDeviceImpl_SetVertexShaderConstantF,
8098     IWineD3DDeviceImpl_GetVertexShaderConstantF,
8099     IWineD3DDeviceImpl_SetViewport,
8100     IWineD3DDeviceImpl_GetViewport,
8101     IWineD3DDeviceImpl_MultiplyTransform,
8102     IWineD3DDeviceImpl_ValidateDevice,
8103     IWineD3DDeviceImpl_ProcessVertices,
8104     /*** State block ***/
8105     IWineD3DDeviceImpl_BeginStateBlock,
8106     IWineD3DDeviceImpl_EndStateBlock,
8107     /*** Scene management ***/
8108     IWineD3DDeviceImpl_BeginScene,
8109     IWineD3DDeviceImpl_EndScene,
8110     IWineD3DDeviceImpl_Present,
8111     IWineD3DDeviceImpl_Clear,
8112     /*** Drawing ***/
8113     IWineD3DDeviceImpl_DrawPrimitive,
8114     IWineD3DDeviceImpl_DrawIndexedPrimitive,
8115     IWineD3DDeviceImpl_DrawPrimitiveUP,
8116     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
8117     IWineD3DDeviceImpl_DrawPrimitiveStrided,
8118     IWineD3DDeviceImpl_DrawRectPatch,
8119     IWineD3DDeviceImpl_DrawTriPatch,
8120     IWineD3DDeviceImpl_DeletePatch,
8121     IWineD3DDeviceImpl_ColorFill,
8122     IWineD3DDeviceImpl_UpdateTexture,
8123     IWineD3DDeviceImpl_UpdateSurface,
8124     IWineD3DDeviceImpl_CopyRects,
8125     IWineD3DDeviceImpl_StretchRect,
8126     IWineD3DDeviceImpl_GetRenderTargetData,
8127     IWineD3DDeviceImpl_GetFrontBufferData,
8128     /*** Internal use IWineD3DDevice methods ***/
8129     IWineD3DDeviceImpl_SetupTextureStates,
8130     /*** object tracking ***/
8131     IWineD3DDeviceImpl_ResourceReleased
8132 };
8133
8134
8135 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
8136     WINED3DRS_ALPHABLENDENABLE   ,
8137     WINED3DRS_ALPHAFUNC          ,
8138     WINED3DRS_ALPHAREF           ,
8139     WINED3DRS_ALPHATESTENABLE    ,
8140     WINED3DRS_BLENDOP            ,
8141     WINED3DRS_COLORWRITEENABLE   ,
8142     WINED3DRS_DESTBLEND          ,
8143     WINED3DRS_DITHERENABLE       ,
8144     WINED3DRS_FILLMODE           ,
8145     WINED3DRS_FOGDENSITY         ,
8146     WINED3DRS_FOGEND             ,
8147     WINED3DRS_FOGSTART           ,
8148     WINED3DRS_LASTPIXEL          ,
8149     WINED3DRS_SHADEMODE          ,
8150     WINED3DRS_SRCBLEND           ,
8151     WINED3DRS_STENCILENABLE      ,
8152     WINED3DRS_STENCILFAIL        ,
8153     WINED3DRS_STENCILFUNC        ,
8154     WINED3DRS_STENCILMASK        ,
8155     WINED3DRS_STENCILPASS        ,
8156     WINED3DRS_STENCILREF         ,
8157     WINED3DRS_STENCILWRITEMASK   ,
8158     WINED3DRS_STENCILZFAIL       ,
8159     WINED3DRS_TEXTUREFACTOR      ,
8160     WINED3DRS_WRAP0              ,
8161     WINED3DRS_WRAP1              ,
8162     WINED3DRS_WRAP2              ,
8163     WINED3DRS_WRAP3              ,
8164     WINED3DRS_WRAP4              ,
8165     WINED3DRS_WRAP5              ,
8166     WINED3DRS_WRAP6              ,
8167     WINED3DRS_WRAP7              ,
8168     WINED3DRS_ZENABLE            ,
8169     WINED3DRS_ZFUNC              ,
8170     WINED3DRS_ZWRITEENABLE
8171 };
8172
8173 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
8174     WINED3DTSS_ADDRESSW              ,
8175     WINED3DTSS_ALPHAARG0             ,
8176     WINED3DTSS_ALPHAARG1             ,
8177     WINED3DTSS_ALPHAARG2             ,
8178     WINED3DTSS_ALPHAOP               ,
8179     WINED3DTSS_BUMPENVLOFFSET        ,
8180     WINED3DTSS_BUMPENVLSCALE         ,
8181     WINED3DTSS_BUMPENVMAT00          ,
8182     WINED3DTSS_BUMPENVMAT01          ,
8183     WINED3DTSS_BUMPENVMAT10          ,
8184     WINED3DTSS_BUMPENVMAT11          ,
8185     WINED3DTSS_COLORARG0             ,
8186     WINED3DTSS_COLORARG1             ,
8187     WINED3DTSS_COLORARG2             ,
8188     WINED3DTSS_COLOROP               ,
8189     WINED3DTSS_RESULTARG             ,
8190     WINED3DTSS_TEXCOORDINDEX         ,
8191     WINED3DTSS_TEXTURETRANSFORMFLAGS
8192 };
8193
8194 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
8195     WINED3DSAMP_ADDRESSU         ,
8196     WINED3DSAMP_ADDRESSV         ,
8197     WINED3DSAMP_ADDRESSW         ,
8198     WINED3DSAMP_BORDERCOLOR      ,
8199     WINED3DSAMP_MAGFILTER        ,
8200     WINED3DSAMP_MINFILTER        ,
8201     WINED3DSAMP_MIPFILTER        ,
8202     WINED3DSAMP_MIPMAPLODBIAS    ,
8203     WINED3DSAMP_MAXMIPLEVEL      ,
8204     WINED3DSAMP_MAXANISOTROPY    ,
8205     WINED3DSAMP_SRGBTEXTURE      ,
8206     WINED3DSAMP_ELEMENTINDEX
8207 };
8208
8209 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
8210     WINED3DRS_AMBIENT                       ,
8211     WINED3DRS_AMBIENTMATERIALSOURCE         ,
8212     WINED3DRS_CLIPPING                      ,
8213     WINED3DRS_CLIPPLANEENABLE               ,
8214     WINED3DRS_COLORVERTEX                   ,
8215     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
8216     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
8217     WINED3DRS_FOGDENSITY                    ,
8218     WINED3DRS_FOGEND                        ,
8219     WINED3DRS_FOGSTART                      ,
8220     WINED3DRS_FOGTABLEMODE                  ,
8221     WINED3DRS_FOGVERTEXMODE                 ,
8222     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
8223     WINED3DRS_LIGHTING                      ,
8224     WINED3DRS_LOCALVIEWER                   ,
8225     WINED3DRS_MULTISAMPLEANTIALIAS          ,
8226     WINED3DRS_MULTISAMPLEMASK               ,
8227     WINED3DRS_NORMALIZENORMALS              ,
8228     WINED3DRS_PATCHEDGESTYLE                ,
8229     WINED3DRS_POINTSCALE_A                  ,
8230     WINED3DRS_POINTSCALE_B                  ,
8231     WINED3DRS_POINTSCALE_C                  ,
8232     WINED3DRS_POINTSCALEENABLE              ,
8233     WINED3DRS_POINTSIZE                     ,
8234     WINED3DRS_POINTSIZE_MAX                 ,
8235     WINED3DRS_POINTSIZE_MIN                 ,
8236     WINED3DRS_POINTSPRITEENABLE             ,
8237     WINED3DRS_RANGEFOGENABLE                ,
8238     WINED3DRS_SPECULARMATERIALSOURCE        ,
8239     WINED3DRS_TWEENFACTOR                   ,
8240     WINED3DRS_VERTEXBLEND
8241 };
8242
8243 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
8244     WINED3DTSS_TEXCOORDINDEX         ,
8245     WINED3DTSS_TEXTURETRANSFORMFLAGS
8246 };
8247
8248 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
8249     WINED3DSAMP_DMAPOFFSET
8250 };