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