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