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