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