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