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