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