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