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