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