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