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