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