wined3d: Show fullscreen rendering windows.
[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     WINED3DLIGHT_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 /* allocate one pbuffer per surface */
75 BOOL pbuffer_per_surface = FALSE;
76
77 /* static function declarations */
78 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
79
80 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil);
81
82 /* helper macros */
83 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
84
85 #define D3DCREATEOBJECTINSTANCE(object, type) { \
86     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
87     D3DMEMCHECK(object, pp##type); \
88     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
89     object->wineD3DDevice = This; \
90     object->parent       = parent; \
91     object->ref          = 1; \
92     *pp##type = (IWineD3D##type *) object; \
93 }
94
95 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
96     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
97     D3DMEMCHECK(object, pp##type); \
98     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
99     object->parent       = parent; \
100     object->ref          = 1; \
101     object->baseShader.device = (IWineD3DDevice*) This; \
102     *pp##type = (IWineD3D##type *) object; \
103 }
104
105 #define  D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
106     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
107     D3DMEMCHECK(object, pp##type); \
108     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
109     object->resource.wineD3DDevice   = This; \
110     object->resource.parent          = parent; \
111     object->resource.resourceType    = d3dtype; \
112     object->resource.ref             = 1; \
113     object->resource.pool            = Pool; \
114     object->resource.format          = Format; \
115     object->resource.usage           = Usage; \
116     object->resource.size            = _size; \
117     /* Check that we have enough video ram left */ \
118     if (Pool == WINED3DPOOL_DEFAULT) { \
119         if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
120             WARN("Out of 'bogus' video memory\n"); \
121             HeapFree(GetProcessHeap(), 0, object); \
122             *pp##type = NULL; \
123             return WINED3DERR_OUTOFVIDEOMEMORY; \
124         } \
125         globalChangeGlRam(_size); \
126     } \
127     object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
128     if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
129         FIXME("Out of memory!\n"); \
130         HeapFree(GetProcessHeap(), 0, object); \
131         *pp##type = NULL; \
132         return WINED3DERR_OUTOFVIDEOMEMORY; \
133     } \
134     *pp##type = (IWineD3D##type *) object; \
135     IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
136     TRACE("(%p) : Created resource %p\n", This, object); \
137 }
138
139 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
140     _basetexture.levels     = Levels; \
141     _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
142     _basetexture.LOD        = 0; \
143     _basetexture.dirty      = TRUE; \
144 }
145
146 /**********************************************************
147  * Global variable / Constants follow
148  **********************************************************/
149 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
150
151 /**********************************************************
152  * Utility functions follow
153  **********************************************************/
154 /* Convert the WINED3DLIGHT properties into equivalent gl lights */
155 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
156
157     float quad_att;
158     float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
159     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
160
161     /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
162     glMatrixMode(GL_MODELVIEW);
163     glPushMatrix();
164     glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
165
166     /* Diffuse: */
167     colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
168     colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
169     colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
170     colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
171     glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
172     checkGLcall("glLightfv");
173
174     /* Specular */
175     colRGBA[0] = lightInfo->OriginalParms.Specular.r;
176     colRGBA[1] = lightInfo->OriginalParms.Specular.g;
177     colRGBA[2] = lightInfo->OriginalParms.Specular.b;
178     colRGBA[3] = lightInfo->OriginalParms.Specular.a;
179     glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
180     checkGLcall("glLightfv");
181
182     /* Ambient */
183     colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
184     colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
185     colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
186     colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
187     glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
188     checkGLcall("glLightfv");
189
190     /* Attenuation - Are these right? guessing... */
191     glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
192     checkGLcall("glLightf");
193     glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
194     checkGLcall("glLightf");
195
196     if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
197         quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
198     } else {
199         quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
200     }
201
202     if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
203     glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
204     checkGLcall("glLightf");
205
206     switch (lightInfo->OriginalParms.Type) {
207     case WINED3DLIGHT_POINT:
208         /* Position */
209         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
210         checkGLcall("glLightfv");
211         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
212         checkGLcall("glLightf");
213         /* FIXME: Range */
214         break;
215
216     case WINED3DLIGHT_SPOT:
217         /* Position */
218         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
219         checkGLcall("glLightfv");
220         /* Direction */
221         glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
222         checkGLcall("glLightfv");
223         glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
224         checkGLcall("glLightf");
225         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
226         checkGLcall("glLightf");
227         /* FIXME: Range */
228         break;
229
230     case WINED3DLIGHT_DIRECTIONAL:
231         /* Direction */
232         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
233         checkGLcall("glLightfv");
234         glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
235         checkGLcall("glLightf");
236         glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
237         checkGLcall("glLightf");
238         break;
239
240     default:
241         FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
242     }
243
244     /* Restore the modelview matrix */
245     glPopMatrix();
246 }
247
248 /**********************************************************
249  * GLSL helper functions follow
250  **********************************************************/
251
252 /** Detach the GLSL pixel or vertex shader object from the shader program */
253 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
254
255     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
256
257     if (shaderObj != 0 && programId != 0) {
258         TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
259         GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
260         checkGLcall("glDetachObjectARB");
261     }
262 }
263
264 /** Delete a GLSL shader program */
265 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
266
267     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
268     
269     if (obj != 0) {
270         TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
271         GL_EXTCALL(glDeleteObjectARB(obj));
272         checkGLcall("glDeleteObjectARB");
273     }
274 }
275
276 /** Delete the list of linked programs this shader is associated with.
277  * Also at this point, check to see if there are any objects left attached
278  * to each GLSL program.  If not, delete the GLSL program object.
279  * This will be run when a device is released. */
280 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
281     
282     struct list *ptr                       = NULL;
283     struct glsl_shader_prog_link *curLink  = NULL;
284     IWineD3DDeviceImpl *This               = (IWineD3DDeviceImpl *)iface;
285     
286     int numAttached = 0;
287     int i;
288     GLhandleARB objList[2];   /* There should never be more than 2 objects attached 
289                                  (one pixel shader and one vertex shader at most) */
290     
291     ptr = list_head( &This->glsl_shader_progs );
292     while (ptr) {
293         /* First, get the current item,
294          * save the link to the next pointer, 
295          * detach and delete shader objects,
296          * then de-allocate the list item's memory */
297         curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
298         ptr = list_next( &This->glsl_shader_progs, ptr );
299
300         /* See if this object is still attached to the program - it may have been detached already */
301         GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
302         TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
303         for (i = 0; i < numAttached; i++) {
304             detach_glsl_shader(iface, objList[i], curLink->programId);
305         }
306         
307         delete_glsl_shader_program(iface, curLink->programId);
308
309         /* Free the uniform locations */
310         HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
311         HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
312
313         /* Free the memory for this list item */    
314         HeapFree(GetProcessHeap(), 0, curLink);
315     }
316 }
317
318 /**********************************************************
319  * IUnknown parts follows
320  **********************************************************/
321
322 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
323 {
324     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
325
326     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
327     if (IsEqualGUID(riid, &IID_IUnknown)
328         || IsEqualGUID(riid, &IID_IWineD3DBase)
329         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
330         IUnknown_AddRef(iface);
331         *ppobj = This;
332         return S_OK;
333     }
334     *ppobj = NULL;
335     return E_NOINTERFACE;
336 }
337
338 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
339     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
340     ULONG refCount = InterlockedIncrement(&This->ref);
341
342     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
343     return refCount;
344 }
345
346 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
347     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
348     ULONG refCount = InterlockedDecrement(&This->ref);
349
350     TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
351
352     if (!refCount) {
353         if (This->fbo) {
354             GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
355         }
356
357         HeapFree(GetProcessHeap(), 0, This->render_targets);
358
359         HeapFree(GetProcessHeap(), 0, This->draw_buffers);
360
361         /* TODO: Clean up all the surfaces and textures! */
362         /* NOTE: You must release the parent if the object was created via a callback
363         ** ***************************/
364
365         /* Delete any GLSL shader programs that may exist */
366         if (This->vs_selected_mode == SHADER_GLSL ||
367             This->ps_selected_mode == SHADER_GLSL)
368             delete_glsl_shader_list(iface);
369
370         /* Release the update stateblock */
371         if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
372             if(This->updateStateBlock != This->stateBlock)
373                 FIXME("(%p) Something's still holding the Update stateblock\n",This);
374         }
375         This->updateStateBlock = NULL;
376         { /* because were not doing proper internal refcounts releasing the primary state block
377             causes recursion with the extra checks in ResourceReleased, to avoid this we have
378             to set this->stateBlock = NULL; first */
379             IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
380             This->stateBlock = NULL;
381
382             /* Release the stateblock */
383             if(IWineD3DStateBlock_Release(stateBlock) > 0){
384                     FIXME("(%p) Something's still holding the Update stateblock\n",This);
385             }
386         }
387
388         if (This->resources != NULL ) {
389             FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
390             dumpResources(This->resources);
391         }
392
393         if(This->contexts) ERR("Context array not freed!\n");
394
395         IWineD3D_Release(This->wineD3D);
396         This->wineD3D = NULL;
397         HeapFree(GetProcessHeap(), 0, This);
398         TRACE("Freed device  %p\n", This);
399         This = NULL;
400     }
401     return refCount;
402 }
403
404 /**********************************************************
405  * IWineD3DDevice implementation follows
406  **********************************************************/
407 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
408     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
409     *pParent = This->parent;
410     IUnknown_AddRef(This->parent);
411     return WINED3D_OK;
412 }
413
414 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
415     IWineD3DDeviceImpl *This = object->resource.wineD3DDevice;  /* Needed for GL_EXTCALL */
416     GLenum error, glUsage;
417     DWORD vboUsage = object->resource.usage;
418     if(object->Flags & VBFLAG_VBOCREATEFAIL) {
419         WARN("Creating a vbo failed once, not trying again\n");
420         return;
421     }
422
423     TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p  Usage(%s)\n", object, debug_d3dusage(vboUsage));
424
425     ENTER_GL();
426     /* Make sure that the gl error is cleared. Do not use checkGLcall
427       * here because checkGLcall just prints a fixme and continues. However,
428       * if an error during VBO creation occurs we can fall back to non-vbo operation
429       * with full functionality(but performance loss)
430       */
431     while(glGetError() != GL_NO_ERROR);
432
433     /* Basically the FVF parameter passed to CreateVertexBuffer is no good
434       * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
435       * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
436       * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
437       * to check if the rhw and color values are in the correct format.
438       */
439
440     GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
441     error = glGetError();
442     if(object->vbo == 0 || error != GL_NO_ERROR) {
443         WARN("Failed to create a VBO with error %d\n", error);
444         goto error;
445     }
446
447     GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
448     error = glGetError();
449     if(error != GL_NO_ERROR) {
450         WARN("Failed to bind the VBO, error %d\n", error);
451         goto error;
452     }
453
454     /* Don't use static, because dx apps tend to update the buffer
455       * quite often even if they specify 0 usage
456       */
457     switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
458         case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
459             TRACE("Gl usage = GL_STREAM_DRAW\n");
460             glUsage = GL_STREAM_DRAW_ARB;
461             break;
462         case D3DUSAGE_WRITEONLY:
463             TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
464             glUsage = GL_DYNAMIC_DRAW_ARB;
465             break;
466         case D3DUSAGE_DYNAMIC:
467             TRACE("Gl usage = GL_STREAM_COPY\n");
468             glUsage = GL_STREAM_COPY_ARB;
469             break;
470         default:
471             TRACE("Gl usage = GL_DYNAMIC_COPY\n");
472             glUsage = GL_DYNAMIC_COPY_ARB;
473             break;
474     }
475
476     /* Reserve memory for the buffer. The amount of data won't change
477       * so we are safe with calling glBufferData once with a NULL ptr and
478       * calling glBufferSubData on updates
479       */
480     GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
481     error = glGetError();
482     if(error != GL_NO_ERROR) {
483         WARN("glBufferDataARB failed with error %d\n", error);
484         goto error;
485     }
486
487     LEAVE_GL();
488
489     return;
490     error:
491     /* Clean up all vbo init, but continue because we can work without a vbo :-) */
492     FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
493     if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
494     object->vbo = 0;
495     object->Flags |= VBFLAG_VBOCREATEFAIL;
496     LEAVE_GL();
497     return;
498 }
499
500 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, 
501                              DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
502                              IUnknown *parent) {
503     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
504     IWineD3DVertexBufferImpl *object;
505     WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
506     int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
507     BOOL conv;
508     D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
509
510     TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
511     *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
512
513     if(Size == 0) return WINED3DERR_INVALIDCALL;
514
515     if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
516         object->resource.allocatedMemory  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
517     }
518     object->fvf = FVF;
519
520     /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
521      * drawStridedFast (half-life 2).
522      *
523      * Basically converting the vertices in the buffer is quite expensive, and observations
524      * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
525      * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
526      *
527      * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
528      * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
529      * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
530      * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
531      * dx7 apps.
532      * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
533      * more. In this call we can convert dx7 buffers too.
534      */
535     conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
536     if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && 
537         (dxVersion > 7 || !conv) ) {
538         CreateVBO(object);
539
540         /* DX7 buffers can be locked directly into the VBO (no conversion, see above */
541         if(dxVersion == 7 && object->vbo) {
542             HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
543             object->resource.allocatedMemory = NULL;
544         }
545
546     }
547     return WINED3D_OK;
548 }
549
550 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage, 
551                                                     WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
552                                                     HANDLE *sharedHandle, IUnknown *parent) {
553     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
554     IWineD3DIndexBufferImpl *object;
555     TRACE("(%p) Creating index buffer\n", This);
556     
557     /* Allocate the storage for the device */
558     D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
559     
560     /*TODO: use VBO's */
561     if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
562         object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
563     }
564
565     TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format, 
566                            debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
567     *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
568
569     return WINED3D_OK;
570 }
571
572 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
573
574     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
575     IWineD3DStateBlockImpl *object;
576     int i, j;
577     HRESULT temp_result;
578
579     D3DCREATEOBJECTINSTANCE(object, StateBlock)
580     object->blockType     = Type;
581
582     /* Special case - Used during initialization to produce a placeholder stateblock
583           so other functions called can update a state block                         */
584     if (Type == WINED3DSBT_INIT) {
585         /* Don't bother increasing the reference count otherwise a device will never
586            be freed due to circular dependencies                                   */
587         return WINED3D_OK;
588     }
589     
590     temp_result = allocate_shader_constants(object);
591     if (WINED3D_OK != temp_result)
592         return temp_result;
593
594     /* Otherwise, might as well set the whole state block to the appropriate values  */
595     if (This->stateBlock != NULL)
596         stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
597     else
598         memset(object->streamFreq, 1, sizeof(object->streamFreq));
599
600     /* Reset the ref and type after kludging it */
601     object->wineD3DDevice = This;
602     object->ref           = 1;
603     object->blockType     = Type;
604
605     TRACE("Updating changed flags appropriate for type %d\n", Type);
606
607     if (Type == WINED3DSBT_ALL) {
608
609         TRACE("ALL => Pretend everything has changed\n");
610         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
611     
612     } else if (Type == WINED3DSBT_PIXELSTATE) {
613
614         TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
615         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
616
617         object->changed.pixelShader = TRUE;
618
619         /* Pixel Shader Constants */
620         for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
621             object->changed.pixelShaderConstantsF[i] = TRUE;
622         for (i = 0; i < MAX_CONST_B; ++i)
623             object->changed.pixelShaderConstantsB[i] = TRUE;
624         for (i = 0; i < MAX_CONST_I; ++i)
625             object->changed.pixelShaderConstantsI[i] = TRUE;
626         
627         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
628             object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
629         }
630         for (j = 0; j < GL_LIMITS(texture_stages); j++) {
631             for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
632                 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
633             }
634         }
635         for (j = 0 ; j < 16; j++) {
636             for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
637
638                 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
639             }
640         }
641
642     } else if (Type == WINED3DSBT_VERTEXSTATE) {
643
644         TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
645         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
646
647         object->changed.vertexShader = TRUE;
648
649         /* Vertex Shader Constants */
650         for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
651             object->changed.vertexShaderConstantsF[i] = TRUE;
652         for (i = 0; i < MAX_CONST_B; ++i)
653             object->changed.vertexShaderConstantsB[i] = TRUE;
654         for (i = 0; i < MAX_CONST_I; ++i)
655             object->changed.vertexShaderConstantsI[i] = TRUE;
656  
657         for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
658             object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
659         }
660         for (j = 0; j < GL_LIMITS(texture_stages); j++) {
661             for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
662                 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
663             }
664         }
665         for (j = 0 ; j < 16; j++){
666             for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
667                 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
668             }
669         }
670
671     /* Duplicate light chain */
672     {
673         PLIGHTINFOEL *src = NULL;
674         PLIGHTINFOEL *dst = NULL;
675         PLIGHTINFOEL *newEl = NULL;
676         src = This->stateBlock->lights;
677         object->lights = NULL;
678
679
680         while (src) {
681             newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
682             if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
683             memcpy(newEl, src, sizeof(PLIGHTINFOEL));
684             newEl->prev = dst;
685             newEl->changed = TRUE;
686             newEl->enabledChanged = TRUE;
687             if (dst == NULL) {
688                 object->lights = newEl;
689             } else {
690                 dst->next = newEl;
691             }
692             dst = newEl;
693             src = src->next;
694         }
695
696      }
697
698     } else {
699         FIXME("Unrecognized state block type %d\n", Type);
700     }
701
702     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
703     return WINED3D_OK;
704 }
705
706
707 /* ************************************
708 MSDN:
709 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
710
711 Discard
712  [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. 
713
714 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.
715
716 ******************************** */
717  
718 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) {
719     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;    
720     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
721     unsigned int pow2Width, pow2Height;
722     unsigned int Size       = 1;
723     const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
724     TRACE("(%p) Create surface\n",This);
725     
726     /** FIXME: Check ranges on the inputs are valid 
727      * MSDN
728      *   MultisampleQuality
729      *    [in] Quality level. The valid range is between zero and one less than the level
730      *    returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. 
731      *    Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
732      *    values of paired render targets, depth stencil surfaces, and the MultiSample type
733      *    must all match.
734       *******************************/
735
736
737     /**
738     * TODO: Discard MSDN
739     * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
740     *
741     * If this flag is set, the contents of the depth stencil buffer will be
742     * invalid after calling either IDirect3DDevice9::Present or  * IDirect3DDevice9::SetDepthStencilSurface
743     * with a different depth surface.
744     *
745     *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
746     ***************************/
747
748     if(MultisampleQuality < 0) {
749         FIXME("Invalid multisample level %d\n", MultisampleQuality);
750         return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
751     }
752
753     if(MultisampleQuality > 0) {
754         FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
755         MultisampleQuality=0;
756     }
757
758     /** FIXME: Check that the format is supported
759     *    by the device.
760       *******************************/
761
762     /* Non-power2 support */
763     if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
764         pow2Width = Width;
765         pow2Height = Height;
766     } else {
767         /* Find the nearest pow2 match */
768         pow2Width = pow2Height = 1;
769         while (pow2Width < Width) pow2Width <<= 1;
770         while (pow2Height < Height) pow2Height <<= 1;
771     }
772
773     if (pow2Width > Width || pow2Height > Height) {
774          /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
775         if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
776                || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
777             FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
778                     This, Width, Height);
779             return WINED3DERR_NOTAVAILABLE;
780         }
781     }
782
783     /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
784      *  it is based around 4x4 pixel blocks it requires padding, so allocate enough
785      *  space!
786       *********************************/
787     if (WINED3DFMT_UNKNOWN == Format) {
788         Size = 0;
789     } else if (Format == WINED3DFMT_DXT1) {
790         /* DXT1 is half byte per pixel */
791        Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
792
793     } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
794                Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
795        Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
796     } else {
797        /* The pitch is a multiple of 4 bytes */
798        Size = ((pow2Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
799        Size *= pow2Height;
800     }
801
802     /** Create and initialise the surface resource **/
803     D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
804     /* "Standalone" surface */
805     IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
806
807     object->currentDesc.Width      = Width;
808     object->currentDesc.Height     = Height;
809     object->currentDesc.MultiSampleType    = MultiSample;
810     object->currentDesc.MultiSampleQuality = MultisampleQuality;
811
812     /* Setup some glformat defaults */
813     object->glDescription.glFormat         = tableEntry->glFormat;
814     object->glDescription.glFormatInternal = tableEntry->glInternal;
815     object->glDescription.glType           = tableEntry->glType;
816
817     object->glDescription.textureName      = 0;
818     object->glDescription.level            = Level;
819     object->glDescription.target           = GL_TEXTURE_2D;
820
821     /* Internal data */
822     object->pow2Width  = pow2Width;
823     object->pow2Height = pow2Height;
824
825     /* Flags */
826     object->Flags      = 0; /* We start without flags set */
827     object->Flags     |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
828     object->Flags     |= Discard ? SFLAG_DISCARD : 0;
829     object->Flags     |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
830     object->Flags     |= Lockable ? SFLAG_LOCKABLE : 0;
831
832
833     if (WINED3DFMT_UNKNOWN != Format) {
834         object->bytesPerPixel = tableEntry->bpp;
835         object->pow2Size = ((pow2Width * object->bytesPerPixel) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
836         object->pow2Size *= pow2Height;
837     } else {
838         object->bytesPerPixel = 0;
839         object->pow2Size      = 0;
840     }
841
842     /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
843
844     TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
845
846     /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
847     * this function is too deep to need to care about things like this.
848     * Levels need to be checked too, and possibly Type since they all affect what can be done.
849     * ****************************************/
850     switch(Pool) {
851     case WINED3DPOOL_SCRATCH:
852         if(!Lockable)
853             FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE "
854                 "which are mutually exclusive, setting lockable to TRUE\n");
855                 Lockable = TRUE;
856     break;
857     case WINED3DPOOL_SYSTEMMEM:
858         if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, "
859                                     "this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
860     case WINED3DPOOL_MANAGED:
861         if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a "
862                                                 "Usage of DYNAMIC which are mutually exclusive, not doing "
863                                                 "anything just telling you.\n");
864     break;
865     case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
866         if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
867            && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
868             WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
869     break;
870     default:
871         FIXME("(%p) Unknown pool %d\n", This, Pool);
872     break;
873     };
874
875     if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
876         FIXME("Trying to create a render target that isn't in the default pool\n");
877     }
878
879     /* mark the texture as dirty so that it gets loaded first time around*/
880     IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
881     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
882            This, Width, Height, Format, debug_d3dformat(Format),
883            (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
884
885     /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
886     if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
887         This->ddraw_primary = (IWineD3DSurface *) object;
888
889     /* Look at the implementation and set the correct Vtable */
890     switch(Impl) {
891         case SURFACE_OPENGL:
892             /* Nothing to do, it's set already */
893             break;
894
895         case SURFACE_GDI:
896             object->lpVtbl = &IWineGDISurface_Vtbl;
897             break;
898
899         default:
900             /* To be sure to catch this */
901             ERR("Unknown requested surface implementation %d!\n", Impl);
902             IWineD3DSurface_Release((IWineD3DSurface *) object);
903             return WINED3DERR_INVALIDCALL;
904     }
905
906     /* Call the private setup routine */
907     return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
908
909 }
910
911 static HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
912                                                  DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
913                                                  IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
914                                                  D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
915
916     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
917     IWineD3DTextureImpl *object;
918     unsigned int i;
919     UINT tmpW;
920     UINT tmpH;
921     HRESULT hr;
922     unsigned int pow2Width;
923     unsigned int pow2Height;
924
925
926     TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
927     TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
928             Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
929
930     /* TODO: It should only be possible to create textures for formats 
931              that are reported as supported */
932     if (WINED3DFMT_UNKNOWN >= Format) {
933         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
934         return WINED3DERR_INVALIDCALL;
935     }
936
937     D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
938     D3DINITIALIZEBASETEXTURE(object->baseTexture);    
939     object->width  = Width;
940     object->height = Height;
941
942     /** Non-power2 support **/
943     if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
944         pow2Width = Width;
945         pow2Height = Height;
946     } else {
947         /* Find the nearest pow2 match */
948         pow2Width = pow2Height = 1;
949         while (pow2Width < Width) pow2Width <<= 1;
950         while (pow2Height < Height) pow2Height <<= 1;
951     }
952
953     /** FIXME: add support for real non-power-two if it's provided by the video card **/
954     /* Precalculated scaling for 'faked' non power of two texture coords */
955     object->pow2scalingFactorX  =  (((float)Width)  / ((float)pow2Width));
956     object->pow2scalingFactorY  =  (((float)Height) / ((float)pow2Height));
957     TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
958
959     /* Calculate levels for mip mapping */
960     if (Levels == 0) {
961         TRACE("calculating levels %d\n", object->baseTexture.levels);
962         object->baseTexture.levels++;
963         tmpW = Width;
964         tmpH = Height;
965         while (tmpW > 1 || tmpH > 1) {
966             tmpW = max(1, tmpW >> 1);
967             tmpH = max(1, tmpH >> 1);
968             object->baseTexture.levels++;
969         }
970         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
971     }
972
973     /* Generate all the surfaces */
974     tmpW = Width;
975     tmpH = Height;
976     for (i = 0; i < object->baseTexture.levels; i++)
977     {
978         /* use the callback to create the texture surface */
979         hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
980         if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
981             FIXME("Failed to create surface  %p\n", object);
982             /* clean up */
983             object->surfaces[i] = NULL;
984             IWineD3DTexture_Release((IWineD3DTexture *)object);
985
986             *ppTexture = NULL;
987             return hr;
988         }
989
990         IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
991         TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
992         /* calculate the next mipmap level */
993         tmpW = max(1, tmpW >> 1);
994         tmpH = max(1, tmpH >> 1);
995     }
996
997     TRACE("(%p) : Created  texture %p\n", This, object);
998     return WINED3D_OK;
999 }
1000
1001 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1002                                                       UINT Width, UINT Height, UINT Depth,
1003                                                       UINT Levels, DWORD Usage,
1004                                                       WINED3DFORMAT Format, WINED3DPOOL Pool,
1005                                                       IWineD3DVolumeTexture **ppVolumeTexture,
1006                                                       HANDLE *pSharedHandle, IUnknown *parent,
1007                                                       D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1008
1009     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
1010     IWineD3DVolumeTextureImpl *object;
1011     unsigned int               i;
1012     UINT                       tmpW;
1013     UINT                       tmpH;
1014     UINT                       tmpD;
1015
1016     /* TODO: It should only be possible to create textures for formats 
1017              that are reported as supported */
1018     if (WINED3DFMT_UNKNOWN >= Format) {
1019         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1020         return WINED3DERR_INVALIDCALL;
1021     }
1022
1023     D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1024     D3DINITIALIZEBASETEXTURE(object->baseTexture);
1025
1026     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1027           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1028
1029     object->width  = Width;
1030     object->height = Height;
1031     object->depth  = Depth;
1032
1033     /* Calculate levels for mip mapping */
1034     if (Levels == 0) {
1035         object->baseTexture.levels++;
1036         tmpW = Width;
1037         tmpH = Height;
1038         tmpD = Depth;
1039         while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1040             tmpW = max(1, tmpW >> 1);
1041             tmpH = max(1, tmpH >> 1);
1042             tmpD = max(1, tmpD >> 1);
1043             object->baseTexture.levels++;
1044         }
1045         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1046     }
1047
1048     /* Generate all the surfaces */
1049     tmpW = Width;
1050     tmpH = Height;
1051     tmpD = Depth;
1052
1053     for (i = 0; i < object->baseTexture.levels; i++)
1054     {
1055         /* Create the volume */
1056         D3DCB_CreateVolume(This->parent, parent, Width, Height, Depth, Format, Pool, Usage,
1057                            (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1058
1059         /* Set its container to this object */
1060         IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1061
1062         /* calcualte the next mipmap level */
1063         tmpW = max(1, tmpW >> 1);
1064         tmpH = max(1, tmpH >> 1);
1065         tmpD = max(1, tmpD >> 1);
1066     }
1067
1068     *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1069     TRACE("(%p) : Created volume texture %p\n", This, object);
1070     return WINED3D_OK;
1071 }
1072
1073 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1074                                                UINT Width, UINT Height, UINT Depth,
1075                                                DWORD Usage,
1076                                                WINED3DFORMAT Format, WINED3DPOOL Pool,
1077                                                IWineD3DVolume** ppVolume,
1078                                                HANDLE* pSharedHandle, IUnknown *parent) {
1079
1080     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
1081     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
1082     const PixelFormatDesc *formatDesc  = getFormatDescEntry(Format);
1083
1084     D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1085
1086     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1087           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1088
1089     object->currentDesc.Width   = Width;
1090     object->currentDesc.Height  = Height;
1091     object->currentDesc.Depth   = Depth;
1092     object->bytesPerPixel       = formatDesc->bpp;
1093
1094     /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1095     object->lockable            = TRUE;
1096     object->locked              = FALSE;
1097     memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1098     object->dirty               = TRUE;
1099
1100     return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1101 }
1102
1103 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1104                                                     UINT Levels, DWORD Usage,
1105                                                     WINED3DFORMAT Format, WINED3DPOOL Pool,
1106                                                     IWineD3DCubeTexture **ppCubeTexture,
1107                                                     HANDLE *pSharedHandle, IUnknown *parent,
1108                                                     D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1109
1110     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1111     IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1112     unsigned int             i, j;
1113     UINT                     tmpW;
1114     HRESULT                  hr;
1115     unsigned int pow2EdgeLength  = EdgeLength;
1116
1117     /* TODO: It should only be possible to create textures for formats 
1118              that are reported as supported */
1119     if (WINED3DFMT_UNKNOWN >= Format) {
1120         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1121         return WINED3DERR_INVALIDCALL;
1122     }
1123
1124     D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1125     D3DINITIALIZEBASETEXTURE(object->baseTexture);
1126
1127     TRACE("(%p) Create Cube Texture\n", This);
1128
1129     /** Non-power2 support **/
1130
1131     /* Find the nearest pow2 match */
1132     pow2EdgeLength = 1;
1133     while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1134
1135     object->edgeLength           = EdgeLength;
1136     /* TODO: support for native non-power 2 */
1137     /* Precalculated scaling for 'faked' non power of two texture coords */
1138     object->pow2scalingFactor    = ((float)EdgeLength) / ((float)pow2EdgeLength);
1139
1140     /* Calculate levels for mip mapping */
1141     if (Levels == 0) {
1142         object->baseTexture.levels++;
1143         tmpW = EdgeLength;
1144         while (tmpW > 1) {
1145             tmpW = max(1, tmpW >> 1);
1146             object->baseTexture.levels++;
1147         }
1148         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1149     }
1150
1151     /* Generate all the surfaces */
1152     tmpW = EdgeLength;
1153     for (i = 0; i < object->baseTexture.levels; i++) {
1154
1155         /* Create the 6 faces */
1156         for (j = 0; j < 6; j++) {
1157
1158             hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool,
1159                                    i /* Level */, &object->surfaces[j][i],pSharedHandle);
1160
1161             if(hr!= WINED3D_OK) {
1162                 /* clean up */
1163                 int k;
1164                 int l;
1165                 for (l = 0; l < j; l++) {
1166                     IWineD3DSurface_Release(object->surfaces[j][i]);
1167                 }
1168                 for (k = 0; k < i; k++) {
1169                     for (l = 0; l < 6; l++) {
1170                     IWineD3DSurface_Release(object->surfaces[l][j]);
1171                     }
1172                 }
1173
1174                 FIXME("(%p) Failed to create surface\n",object);
1175                 HeapFree(GetProcessHeap(),0,object);
1176                 *ppCubeTexture = NULL;
1177                 return hr;
1178             }
1179             IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1180             TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1181         }
1182         tmpW = max(1, tmpW >> 1);
1183     }
1184
1185     TRACE("(%p) : Created Cube Texture %p\n", This, object);
1186     *ppCubeTexture = (IWineD3DCubeTexture *) object;
1187     return WINED3D_OK;
1188 }
1189
1190 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1191     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1192     IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1193
1194     if (NULL == ppQuery) {
1195         /* Just a check to see if we support this type of query */
1196         HRESULT hr = WINED3DERR_NOTAVAILABLE;
1197         switch(Type) {
1198         case WINED3DQUERYTYPE_OCCLUSION:
1199             TRACE("(%p) occlusion query\n", This);
1200             if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1201                 hr = WINED3D_OK;
1202             else
1203                 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1204             break;
1205         case WINED3DQUERYTYPE_VCACHE:
1206         case WINED3DQUERYTYPE_RESOURCEMANAGER:
1207         case WINED3DQUERYTYPE_VERTEXSTATS:
1208         case WINED3DQUERYTYPE_EVENT:
1209         case WINED3DQUERYTYPE_TIMESTAMP:
1210         case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1211         case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1212         case WINED3DQUERYTYPE_PIPELINETIMINGS:
1213         case WINED3DQUERYTYPE_INTERFACETIMINGS:
1214         case WINED3DQUERYTYPE_VERTEXTIMINGS:
1215         case WINED3DQUERYTYPE_PIXELTIMINGS:
1216         case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1217         case WINED3DQUERYTYPE_CACHEUTILIZATION:
1218         default:
1219             FIXME("(%p) Unhandled query type %d\n", This, Type);
1220         }
1221         return hr;
1222     }
1223
1224     D3DCREATEOBJECTINSTANCE(object, Query)
1225     object->type         = Type;
1226     /* allocated the 'extended' data based on the type of query requested */
1227     switch(Type){
1228     case WINED3DQUERYTYPE_OCCLUSION:
1229         if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1230             TRACE("(%p) Allocating data for an occlusion query\n", This);
1231             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1232             GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1233             break;
1234         }
1235     case WINED3DQUERYTYPE_VCACHE:
1236     case WINED3DQUERYTYPE_RESOURCEMANAGER:
1237     case WINED3DQUERYTYPE_VERTEXSTATS:
1238     case WINED3DQUERYTYPE_EVENT:
1239     case WINED3DQUERYTYPE_TIMESTAMP:
1240     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1241     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1242     case WINED3DQUERYTYPE_PIPELINETIMINGS:
1243     case WINED3DQUERYTYPE_INTERFACETIMINGS:
1244     case WINED3DQUERYTYPE_VERTEXTIMINGS:
1245     case WINED3DQUERYTYPE_PIXELTIMINGS:
1246     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1247     case WINED3DQUERYTYPE_CACHEUTILIZATION:
1248     default:
1249         object->extendedData = 0;
1250         FIXME("(%p) Unhandled query type %d\n",This , Type);
1251     }
1252     TRACE("(%p) : Created Query %p\n", This, object);
1253     return WINED3D_OK;
1254 }
1255
1256 /*****************************************************************************
1257  * IWineD3DDeviceImpl_SetupFullscreenWindow
1258  *
1259  * Helper function that modifies a HWND's Style and ExStyle for proper
1260  * fullscreen use.
1261  *
1262  * Params:
1263  *  iface: Pointer to the IWineD3DDevice interface
1264  *  window: Window to setup
1265  *
1266  *****************************************************************************/
1267 static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *iface, HWND window) {
1268     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1269
1270     LONG style, exStyle;
1271     /* Don't do anything if an original style is stored.
1272      * That shouldn't happen
1273      */
1274     TRACE("(%p): Setting up window %p for exclusive mode\n", This, window);
1275     if (This->style && This->exStyle) {
1276         ERR("(%p): Want to change the window parameters of HWND %p, but "
1277             "another style is stored for restoration afterwards\n", This, window);
1278     }
1279
1280     /* Get the parameters and save them */
1281     style = GetWindowLongW(window, GWL_STYLE);
1282     exStyle = GetWindowLongW(window, GWL_EXSTYLE);
1283     This->style = style;
1284     This->exStyle = exStyle;
1285
1286     /* Filter out window decorations */
1287     style &= ~WS_CAPTION;
1288     style &= ~WS_THICKFRAME;
1289     exStyle &= ~WS_EX_WINDOWEDGE;
1290     exStyle &= ~WS_EX_CLIENTEDGE;
1291
1292     /* Make sure the window is managed, otherwise we won't get keyboard input */
1293     style |= WS_POPUP | WS_SYSMENU;
1294
1295     TRACE("Old style was %08x,%08x, setting to %08x,%08x\n",
1296           This->style, This->exStyle, style, exStyle);
1297
1298     SetWindowLongW(window, GWL_STYLE, style);
1299     SetWindowLongW(window, GWL_EXSTYLE, exStyle);
1300
1301     /* Inform the window about the update. */
1302     SetWindowPos(window, HWND_TOP, 0, 0,
1303             This->ddraw_width, This->ddraw_height, SWP_FRAMECHANGED);
1304     ShowWindow(window, TRUE);
1305 }
1306
1307 /*****************************************************************************
1308  * IWineD3DDeviceImpl_RestoreWindow
1309  *
1310  * Helper function that restores a windows' properties when taking it out
1311  * of fullscreen mode
1312  *
1313  * Params:
1314  *  iface: Pointer to the IWineD3DDevice interface
1315  *  window: Window to setup
1316  *
1317  *****************************************************************************/
1318 static void WINAPI IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND window) {
1319     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1320
1321     /* This could be a DDSCL_NORMAL -> DDSCL_NORMAL
1322      * switch, do nothing
1323      */
1324     if (!This->style && !This->exStyle) return;
1325
1326     TRACE("(%p): Restoring window settings of window %p to %08x, %08x\n",
1327           This, window, This->style, This->exStyle);
1328
1329     SetWindowLongW(window, GWL_STYLE, This->style);
1330     SetWindowLongW(window, GWL_EXSTYLE, This->exStyle);
1331
1332     /* Delete the old values */
1333     This->style = 0;
1334     This->exStyle = 0;
1335
1336     /* Inform the window about the update */
1337     SetWindowPos(window, 0 /* InsertAfter, ignored */,
1338                  0, 0, 0, 0, /* Pos, Size, ignored */
1339                  SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
1340 }
1341
1342 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1343 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS*  pPresentationParameters,                                                                   IWineD3DSwapChain** ppSwapChain,
1344                                                             IUnknown* parent,
1345                                                             D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1346                                                             D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1347     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1348
1349     HDC                     hDc;
1350     IWineD3DSwapChainImpl  *object; /** NOTE: impl ref allowed since this is a create function **/
1351     HRESULT                 hr = WINED3D_OK;
1352     IUnknown               *bufferParent;
1353     Display                *display;
1354
1355     TRACE("(%p) : Created Aditional Swap Chain\n", This);
1356
1357    /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1358    * does a device hold a reference to a swap chain giving them a lifetime of the device
1359    * or does the swap chain notify the device of its destruction.
1360     *******************************/
1361
1362     /* Check the params */
1363     if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1364         ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1365         return WINED3DERR_INVALIDCALL;
1366     } else if (*pPresentationParameters->BackBufferCount > 1) {
1367         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");
1368     }
1369
1370     D3DCREATEOBJECTINSTANCE(object, SwapChain)
1371
1372     /*********************
1373     * Lookup the window Handle and the relating X window handle
1374     ********************/
1375
1376     /* Setup hwnd we are using, plus which display this equates to */
1377     object->win_handle = *(pPresentationParameters->hDeviceWindow);
1378     if (!object->win_handle) {
1379         object->win_handle = This->createParms.hFocusWindow;
1380     }
1381
1382     object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1383     if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1384         ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1385         return WINED3DERR_NOTAVAILABLE;
1386     }
1387     hDc                = GetDC(object->win_handle);
1388     display            = get_display(hDc);
1389     ReleaseDC(object->win_handle, hDc);
1390     TRACE("Using a display of %p %p\n", display, hDc);
1391
1392     if (NULL == display || NULL == hDc) {
1393         WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1394         return WINED3DERR_NOTAVAILABLE;
1395     }
1396
1397     if (object->win == 0) {
1398         WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1399         return WINED3DERR_NOTAVAILABLE;
1400     }
1401
1402     object->orig_width = GetSystemMetrics(SM_CXSCREEN);
1403     object->orig_height = GetSystemMetrics(SM_CYSCREEN);
1404
1405     /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1406      *  then the corresponding dimension of the client area of the hDeviceWindow
1407      *  (or the focus window, if hDeviceWindow is NULL) is taken.
1408       **********************/
1409
1410     if (*(pPresentationParameters->Windowed) &&
1411         ((*(pPresentationParameters->BackBufferWidth)  == 0) ||
1412          (*(pPresentationParameters->BackBufferHeight) == 0))) {
1413
1414         RECT Rect;
1415         GetClientRect(object->win_handle, &Rect);
1416
1417         if (*(pPresentationParameters->BackBufferWidth) == 0) {
1418            *(pPresentationParameters->BackBufferWidth) = Rect.right;
1419            TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1420         }
1421         if (*(pPresentationParameters->BackBufferHeight) == 0) {
1422            *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1423            TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1424         }
1425     }
1426
1427     /* Put the correct figures in the presentation parameters */
1428     TRACE("Copying across presentation parameters\n");
1429     object->presentParms.BackBufferWidth                = *(pPresentationParameters->BackBufferWidth);
1430     object->presentParms.BackBufferHeight               = *(pPresentationParameters->BackBufferHeight);
1431     object->presentParms.BackBufferFormat               = *(pPresentationParameters->BackBufferFormat);
1432     object->presentParms.BackBufferCount                = *(pPresentationParameters->BackBufferCount);
1433     object->presentParms.MultiSampleType                = *(pPresentationParameters->MultiSampleType);
1434     object->presentParms.MultiSampleQuality             = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1435     object->presentParms.SwapEffect                     = *(pPresentationParameters->SwapEffect);
1436     object->presentParms.hDeviceWindow                  = *(pPresentationParameters->hDeviceWindow);
1437     object->presentParms.Windowed                       = *(pPresentationParameters->Windowed);
1438     object->presentParms.EnableAutoDepthStencil         = *(pPresentationParameters->EnableAutoDepthStencil);
1439     object->presentParms.AutoDepthStencilFormat         = *(pPresentationParameters->AutoDepthStencilFormat);
1440     object->presentParms.Flags                          = *(pPresentationParameters->Flags);
1441     object->presentParms.FullScreen_RefreshRateInHz     = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1442     object->presentParms.PresentationInterval           = *(pPresentationParameters->PresentationInterval);
1443
1444     TRACE("calling rendertarget CB\n");
1445     hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1446                              parent,
1447                              object->presentParms.BackBufferWidth,
1448                              object->presentParms.BackBufferHeight,
1449                              object->presentParms.BackBufferFormat,
1450                              object->presentParms.MultiSampleType,
1451                              object->presentParms.MultiSampleQuality,
1452                              TRUE /* Lockable */,
1453                              &object->frontBuffer,
1454                              NULL /* pShared (always null)*/);
1455     if (object->frontBuffer != NULL) {
1456         IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1457     } else {
1458         ERR("Failed to create the front buffer\n");
1459         goto error;
1460     }
1461
1462     /**
1463     * Create an opengl context for the display visual
1464     *  NOTE: the visual is chosen as the window is created and the glcontext cannot
1465     *     use different properties after that point in time. FIXME: How to handle when requested format
1466     *     doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1467     *     it chooses is identical to the one already being used!
1468      **********************************/
1469
1470     /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1471     ENTER_GL();
1472     object->context = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, display, object->win);
1473     LEAVE_GL();
1474
1475     if (!object->context) {
1476         ERR("Failed to create a new context\n");
1477         hr = WINED3DERR_NOTAVAILABLE;
1478         goto error;
1479     } else {
1480         TRACE("Context created (HWND=%p, glContext=%p, Window=%ld)\n",
1481                object->win_handle, object->context->glCtx, object->win);
1482     }
1483
1484    /*********************
1485    * Windowed / Fullscreen
1486    *******************/
1487
1488    /**
1489    * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1490    * so we should really check to see if there is a fullscreen swapchain already
1491    * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1492     **************************************/
1493
1494    if (!*(pPresentationParameters->Windowed)) {
1495
1496         DEVMODEW devmode;
1497         HDC      hdc;
1498         int      bpp = 0;
1499         RECT     clip_rc;
1500
1501         /* Get info on the current display setup */
1502         hdc = GetDC(0);
1503         bpp = GetDeviceCaps(hdc, BITSPIXEL);
1504         ReleaseDC(0, hdc);
1505
1506         /* Change the display settings */
1507         memset(&devmode, 0, sizeof(DEVMODEW));
1508         devmode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1509         devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1510         devmode.dmPelsWidth  = *(pPresentationParameters->BackBufferWidth);
1511         devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1512         MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1513         ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1514
1515         /* For GetDisplayMode */
1516         This->ddraw_width = devmode.dmPelsWidth;
1517         This->ddraw_height = devmode.dmPelsHeight;
1518         This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1519
1520         IWineD3DDeviceImpl_SetupFullscreenWindow(iface, object->win_handle);
1521
1522         /* And finally clip mouse to our screen */
1523         SetRect(&clip_rc, 0, 0, devmode.dmPelsWidth, devmode.dmPelsHeight);
1524         ClipCursor(&clip_rc);
1525     }
1526
1527    /*********************
1528    * Create the back, front and stencil buffers
1529    *******************/
1530     if(object->presentParms.BackBufferCount > 0) {
1531         int i;
1532
1533         object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1534         if(!object->backBuffer) {
1535             ERR("Out of memory\n");
1536             hr = E_OUTOFMEMORY;
1537             goto error;
1538         }
1539
1540         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1541             TRACE("calling rendertarget CB\n");
1542             hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1543                                     parent,
1544                                     object->presentParms.BackBufferWidth,
1545                                     object->presentParms.BackBufferHeight,
1546                                     object->presentParms.BackBufferFormat,
1547                                     object->presentParms.MultiSampleType,
1548                                     object->presentParms.MultiSampleQuality,
1549                                     TRUE /* Lockable */,
1550                                     &object->backBuffer[i],
1551                                     NULL /* pShared (always null)*/);
1552             if(hr == WINED3D_OK && object->backBuffer[i]) {
1553                 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1554             } else {
1555                 ERR("Cannot create new back buffer\n");
1556                 goto error;
1557             }
1558             ENTER_GL();
1559             glDrawBuffer(GL_BACK);
1560             checkGLcall("glDrawBuffer(GL_BACK)");
1561             LEAVE_GL();
1562         }
1563     } else {
1564         object->backBuffer = NULL;
1565
1566         /* Single buffering - draw to front buffer */
1567         ENTER_GL();
1568         glDrawBuffer(GL_FRONT);
1569         checkGLcall("glDrawBuffer(GL_FRONT)");
1570         LEAVE_GL();
1571     }
1572
1573     /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1574     if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1575         TRACE("Creating depth stencil buffer\n");
1576         if (This->depthStencilBuffer == NULL ) {
1577             hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1578                                     parent,
1579                                     object->presentParms.BackBufferWidth,
1580                                     object->presentParms.BackBufferHeight,
1581                                     object->presentParms.AutoDepthStencilFormat,
1582                                     object->presentParms.MultiSampleType,
1583                                     object->presentParms.MultiSampleQuality,
1584                                     FALSE /* FIXME: Discard */,
1585                                     &This->depthStencilBuffer,
1586                                     NULL /* pShared (always null)*/  );
1587             if (This->depthStencilBuffer != NULL)
1588                 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1589         }
1590
1591         /** TODO: A check on width, height and multisample types
1592         *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1593          ****************************/
1594         object->wantsDepthStencilBuffer = TRUE;
1595     } else {
1596         object->wantsDepthStencilBuffer = FALSE;
1597     }
1598
1599     TRACE("Created swapchain %p\n", object);
1600     TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1601     return WINED3D_OK;
1602
1603 error:
1604     if (object->backBuffer) {
1605         int i;
1606         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1607             if(object->backBuffer[i]) {
1608                 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1609                 IUnknown_Release(bufferParent); /* once for the get parent */
1610                 if (IUnknown_Release(bufferParent) > 0) {
1611                     FIXME("(%p) Something's still holding the back buffer\n",This);
1612                 }
1613             }
1614         }
1615         HeapFree(GetProcessHeap(), 0, object->backBuffer);
1616         object->backBuffer = NULL;
1617     }
1618     if(object->context) {
1619         DestroyContext(This, object->context);
1620     }
1621     if(object->frontBuffer) {
1622         IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1623         IUnknown_Release(bufferParent); /* once for the get parent */
1624         if (IUnknown_Release(bufferParent) > 0) {
1625             FIXME("(%p) Something's still holding the front buffer\n",This);
1626         }
1627     }
1628     if(object) HeapFree(GetProcessHeap(), 0, object);
1629     return hr;
1630 }
1631
1632 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1633 static UINT     WINAPI  IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1634     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1635     TRACE("(%p)\n", This);
1636
1637     return This->NumberOfSwapChains;
1638 }
1639
1640 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1641     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1642     TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1643
1644     if(iSwapChain < This->NumberOfSwapChains) {
1645         *pSwapChain = This->swapchains[iSwapChain];
1646         IWineD3DSwapChain_AddRef(*pSwapChain);
1647         TRACE("(%p) returning %p\n", This, *pSwapChain);
1648         return WINED3D_OK;
1649     } else {
1650         TRACE("Swapchain out of range\n");
1651         *pSwapChain = NULL;
1652         return WINED3DERR_INVALIDCALL;
1653     }
1654 }
1655
1656 /*****
1657  * Vertex Declaration
1658  *****/
1659 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1660     IWineD3DDeviceImpl            *This   = (IWineD3DDeviceImpl *)iface;
1661     IWineD3DVertexDeclarationImpl *object = NULL;
1662     HRESULT hr = WINED3D_OK;
1663     TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1664     D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1665     object->allFVF = 0;
1666
1667     hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1668
1669     return hr;
1670 }
1671
1672 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1673 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1674     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1675     IWineD3DVertexShaderImpl *object;  /* NOTE: impl usage is ok, this is a create */
1676     HRESULT hr = WINED3D_OK;
1677     D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1678     object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1679
1680     TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1681
1682     /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1683     /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1684     if (pDeclaration != NULL) {
1685         IWineD3DVertexDeclaration *vertexDeclaration;
1686         hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1687         if (WINED3D_OK == hr) {
1688             TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1689             object->vertexDeclaration = vertexDeclaration;
1690         } else {
1691             FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1692             IWineD3DVertexShader_Release(*ppVertexShader);
1693             return WINED3DERR_INVALIDCALL;
1694         }
1695     }
1696
1697     hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1698
1699     if (WINED3D_OK != hr) {
1700         FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1701         IWineD3DVertexShader_Release(*ppVertexShader);
1702         return WINED3DERR_INVALIDCALL;
1703     }
1704
1705 #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. */
1706     if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1707         /* Foo */
1708     } else {
1709         /* Bar */
1710     }
1711
1712 #endif
1713
1714     return WINED3D_OK;
1715 }
1716
1717 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1718     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1719     IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1720     HRESULT hr = WINED3D_OK;
1721
1722     D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
1723     object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1724     hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1725     if (WINED3D_OK == hr) {
1726         TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1727     } else {
1728         WARN("(%p) : Failed to create pixel shader\n", This);
1729     }
1730
1731     return hr;
1732 }
1733
1734 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1735     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1736     IWineD3DPaletteImpl *object;
1737     HRESULT hr;
1738     TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1739
1740     /* Create the new object */
1741     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1742     if(!object) {
1743         ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1744         return E_OUTOFMEMORY;
1745     }
1746
1747     object->lpVtbl = &IWineD3DPalette_Vtbl;
1748     object->ref = 1;
1749     object->Flags = Flags;
1750     object->parent = Parent;
1751     object->wineD3DDevice = This;
1752     object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1753         
1754     object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1755
1756     if(!object->hpal) {
1757         HeapFree( GetProcessHeap(), 0, object);
1758         return E_OUTOFMEMORY;
1759     }
1760
1761     hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1762     if(FAILED(hr)) {
1763         IWineD3DPalette_Release((IWineD3DPalette *) object);
1764         return hr;
1765     }
1766
1767     *Palette = (IWineD3DPalette *) object;
1768
1769     return WINED3D_OK;
1770 }
1771
1772 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1773     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1774     IWineD3DSwapChainImpl *swapchain;
1775     DWORD state;
1776
1777     TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1778     if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1779
1780     /* TODO: Test if OpenGL is compiled in and loaded */
1781
1782     /* Initialize the texture unit mapping to a 1:1 mapping */
1783     for(state = 0; state < MAX_SAMPLERS; state++) {
1784         This->texUnitMap[state] = state;
1785     }
1786     This->oneToOneTexUnitMap = TRUE;
1787
1788     /* Setup the implicit swapchain */
1789     TRACE("Creating implicit swapchain\n");
1790     if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
1791         WARN("Failed to create implicit swapchain\n");
1792         return WINED3DERR_INVALIDCALL;
1793     }
1794
1795     This->NumberOfSwapChains = 1;
1796     This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1797     if(!This->swapchains) {
1798         ERR("Out of memory!\n");
1799         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1800         return E_OUTOFMEMORY;
1801     }
1802     This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1803
1804     if(swapchain->backBuffer && swapchain->backBuffer[0]) {
1805         TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1806         This->render_targets[0] = swapchain->backBuffer[0];
1807         This->lastActiveRenderTarget = swapchain->backBuffer[0];
1808     }
1809     else {
1810         TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1811         This->render_targets[0] = swapchain->frontBuffer;
1812         This->lastActiveRenderTarget = swapchain->frontBuffer;
1813     }
1814     IWineD3DSurface_AddRef(This->render_targets[0]);
1815     This->activeContext = swapchain->context;
1816
1817     /* Depth Stencil support */
1818     This->stencilBufferTarget = This->depthStencilBuffer;
1819     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
1820         set_depth_stencil_fbo(iface, This->depthStencilBuffer);
1821     }
1822     if (NULL != This->stencilBufferTarget) {
1823         IWineD3DSurface_AddRef(This->stencilBufferTarget);
1824     }
1825
1826     /* Set up some starting GL setup */
1827     ENTER_GL();
1828     /*
1829     * Initialize openGL extension related variables
1830     *  with Default values
1831     */
1832
1833     ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->context->display);
1834     /* Setup all the devices defaults */
1835     IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1836 #if 0
1837     IWineD3DImpl_CheckGraphicsMemory();
1838 #endif
1839
1840     /* Initialize our list of GLSL programs */
1841     list_init(&This->glsl_shader_progs);
1842
1843     { /* Set a default viewport */
1844         WINED3DVIEWPORT vp;
1845         vp.X      = 0;
1846         vp.Y      = 0;
1847         vp.Width  = *(pPresentationParameters->BackBufferWidth);
1848         vp.Height = *(pPresentationParameters->BackBufferHeight);
1849         vp.MinZ   = 0.0f;
1850         vp.MaxZ   = 1.0f;
1851         IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1852     }
1853
1854     /* Initialize the current view state */
1855     This->view_ident = 1;
1856     This->contexts[0]->last_was_rhw = 0;
1857     glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1858     checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
1859     TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1860     LEAVE_GL();
1861
1862     /* Clear the screen */
1863     IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
1864
1865     This->d3d_initialized = TRUE;
1866     return WINED3D_OK;
1867 }
1868
1869 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
1870     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1871     int sampler;
1872     uint i;
1873     TRACE("(%p)\n", This);
1874
1875     if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1876
1877     /* Delete the pbuffer context if there is any */
1878     if(This->pbufferContext) DestroyContext(This, This->pbufferContext);
1879
1880     /* Delete the mouse cursor texture */
1881     if(This->cursorTexture) {
1882         ENTER_GL();
1883         glDeleteTextures(1, &This->cursorTexture);
1884         LEAVE_GL();
1885         This->cursorTexture = 0;
1886     }
1887
1888     for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
1889         IWineD3DDevice_SetTexture(iface, sampler, NULL);
1890     }
1891
1892     /* Release the buffers (with sanity checks)*/
1893     TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1894     if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1895         if(This->depthStencilBuffer != This->stencilBufferTarget)
1896             FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1897     }
1898     This->stencilBufferTarget = NULL;
1899
1900     TRACE("Releasing the render target at %p\n", This->render_targets[0]);
1901     if(IWineD3DSurface_Release(This->render_targets[0]) >0){
1902           /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1903     }
1904     TRACE("Setting rendertarget to NULL\n");
1905     This->render_targets[0] = NULL;
1906
1907     if (This->depthStencilBuffer) {
1908         if(D3DCB_DestroyDepthStencilSurface(This->depthStencilBuffer) > 0) {
1909             FIXME("(%p) Something's still holding the depthStencilBuffer\n", This);
1910         }
1911         This->depthStencilBuffer = NULL;
1912     }
1913
1914     for(i=0; i < This->NumberOfSwapChains; i++) {
1915         TRACE("Releasing the implicit swapchain %d\n", i);
1916         if (D3DCB_DestroySwapChain(This->swapchains[i])  > 0) {
1917             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1918         }
1919     }
1920
1921     HeapFree(GetProcessHeap(), 0, This->swapchains);
1922     This->swapchains = NULL;
1923     This->NumberOfSwapChains = 0;
1924
1925     This->d3d_initialized = FALSE;
1926     return WINED3D_OK;
1927 }
1928
1929 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
1930     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1931     TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
1932
1933     /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
1934      * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
1935      * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
1936      * separately.
1937      */
1938     This->ddraw_fullscreen = fullscreen;
1939 }
1940
1941 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
1942     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1943
1944     DEVMODEW DevModeW;
1945     int i;
1946     const PixelFormatDesc *formatDesc  = getFormatDescEntry(pixelformat);
1947
1948     TRACE("(%p)->(%x,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
1949
1950     for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
1951         /* Ignore some modes if a description was passed */
1952         if ( (Width > 0)  && (Width != DevModeW.dmPelsWidth)) continue;
1953         if ( (Height > 0)  && (Height != DevModeW.dmPelsHeight)) continue;
1954         if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
1955
1956         TRACE("Enumerating %dx%d@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
1957
1958         if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
1959             return D3D_OK;
1960     }
1961
1962     return D3D_OK;
1963 }
1964
1965 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1966     DEVMODEW devmode;
1967     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1968     LONG ret;
1969     const PixelFormatDesc *formatDesc  = getFormatDescEntry(pMode->Format);
1970     RECT clip_rc;
1971
1972     TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1973
1974     /* Resize the screen even without a window:
1975      * The app could have unset it with SetCooperativeLevel, but not called
1976      * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1977      * but we don't have any hwnd
1978      */
1979
1980     devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1981     devmode.dmBitsPerPel = formatDesc->bpp * 8;
1982     if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
1983     devmode.dmPelsWidth  = pMode->Width;
1984     devmode.dmPelsHeight = pMode->Height;
1985
1986     devmode.dmDisplayFrequency = pMode->RefreshRate;
1987     if (pMode->RefreshRate != 0)  {
1988         devmode.dmFields |= DM_DISPLAYFREQUENCY;
1989     }
1990
1991     /* Only change the mode if necessary */
1992     if( (This->ddraw_width == pMode->Width) &&
1993         (This->ddraw_height == pMode->Height) &&
1994         (This->ddraw_format == pMode->Format) &&
1995         (pMode->RefreshRate == 0) ) {
1996         return D3D_OK;
1997     }
1998
1999     ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2000     if (ret != DISP_CHANGE_SUCCESSFUL) {
2001         if(devmode.dmDisplayFrequency != 0) {
2002             WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2003             devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2004             devmode.dmDisplayFrequency = 0;
2005             ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2006         }
2007         if(ret != DISP_CHANGE_SUCCESSFUL) {
2008             return DDERR_INVALIDMODE;
2009         }
2010     }
2011
2012     /* Store the new values */
2013     This->ddraw_width = pMode->Width;
2014     This->ddraw_height = pMode->Height;
2015     This->ddraw_format = pMode->Format;
2016
2017     /* Only do this with a window of course */
2018     if(This->ddraw_window)
2019       MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2020
2021     /* And finally clip mouse to our screen */
2022     SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
2023     ClipCursor(&clip_rc);
2024
2025     return WINED3D_OK;
2026 }
2027
2028 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2029    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2030    *ppD3D= This->wineD3D;
2031    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
2032    IWineD3D_AddRef(*ppD3D);
2033    return WINED3D_OK;
2034 }
2035
2036 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2037     /** NOTE: There's a probably  a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
2038     * into the video ram as possible and seeing how many fit
2039     * you can also get the correct initial value from nvidia and ATI's driver via X
2040     * texture memory is video memory + AGP memory
2041     *******************/
2042     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2043     static BOOL showfixmes = TRUE;
2044     if (showfixmes) {
2045         FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2046          (wined3d_settings.emulated_textureram/(1024*1024)),
2047          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2048          showfixmes = FALSE;
2049     }
2050     TRACE("(%p) : simulating %dMB, returning %dMB left\n",  This,
2051          (wined3d_settings.emulated_textureram/(1024*1024)),
2052          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2053     /* return simulated texture memory left */
2054     return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2055 }
2056
2057
2058
2059 /*****
2060  * Get / Set FVF
2061  *****/
2062 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2063     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2064
2065     /* Update the current state block */
2066     This->updateStateBlock->changed.fvf      = TRUE;
2067     This->updateStateBlock->set.fvf          = TRUE;
2068
2069     if(This->updateStateBlock->fvf == fvf) {
2070         TRACE("Application is setting the old fvf over, nothing to do\n");
2071         return WINED3D_OK;
2072     }
2073
2074     This->updateStateBlock->fvf              = fvf;
2075     TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2076     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
2077     return WINED3D_OK;
2078 }
2079
2080
2081 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2082     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2083     TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2084     *pfvf = This->stateBlock->fvf;
2085     return WINED3D_OK;
2086 }
2087
2088 /*****
2089  * Get / Set Stream Source
2090  *****/
2091 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2092         IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
2093     IWineD3DVertexBuffer     *oldSrc;
2094
2095     /**TODO: instance and index data, see
2096     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2097     and
2098     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2099      **************/
2100
2101     /* D3d9 only, but shouldn't  hurt d3d8 */
2102     UINT streamFlags;
2103
2104     streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2105     if (streamFlags) {
2106         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2107            FIXME("stream index data not supported\n");
2108         }
2109         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2110            FIXME("stream instance data not supported\n");
2111         }
2112     }
2113
2114     StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2115
2116     if (StreamNumber >= MAX_STREAMS) {
2117         WARN("Stream out of range %d\n", StreamNumber);
2118         return WINED3DERR_INVALIDCALL;
2119     }
2120
2121     oldSrc = This->stateBlock->streamSource[StreamNumber];
2122     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2123
2124     This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2125     This->updateStateBlock->set.streamSource[StreamNumber]     = TRUE;
2126
2127     if(oldSrc == pStreamData &&
2128        This->updateStateBlock->streamStride[StreamNumber] == Stride &&
2129        This->updateStateBlock->streamOffset[StreamNumber] == OffsetInBytes &&
2130        This->updateStateBlock->streamFlags[StreamNumber] == streamFlags) {
2131        TRACE("Application is setting the old values over, nothing to do\n");
2132        return WINED3D_OK;
2133     }
2134
2135     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
2136     if (pStreamData) {
2137         This->updateStateBlock->streamStride[StreamNumber]     = Stride;
2138         This->updateStateBlock->streamOffset[StreamNumber]     = OffsetInBytes;
2139     }
2140     This->updateStateBlock->streamFlags[StreamNumber]          = streamFlags;
2141
2142     /* Handle recording of state blocks */
2143     if (This->isRecordingState) {
2144         TRACE("Recording... not performing anything\n");
2145         return WINED3D_OK;
2146     }
2147
2148     /* Same stream object: no action */
2149     if (oldSrc == pStreamData)
2150         return WINED3D_OK;
2151
2152     /* Need to do a getParent and pass the reffs up */
2153     /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2154     which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2155     so for now, just count internally   */
2156     if (pStreamData != NULL) {
2157         IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2158         InterlockedIncrement(&vbImpl->bindCount);
2159     }
2160     if (oldSrc != NULL) {
2161         InterlockedDecrement(&((IWineD3DVertexBufferImpl *) oldSrc)->bindCount);
2162     }
2163
2164     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2165
2166     return WINED3D_OK;
2167 }
2168
2169 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2170     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2171     UINT streamFlags;
2172
2173     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2174            This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2175
2176
2177     streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2178     if (streamFlags) {
2179         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2180            FIXME("stream index data not supported\n");
2181         }
2182         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2183             FIXME("stream instance data not supported\n");
2184         }
2185     }
2186
2187     StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2188
2189     if (StreamNumber >= MAX_STREAMS) {
2190         WARN("Stream out of range %d\n", StreamNumber);
2191         return WINED3DERR_INVALIDCALL;
2192     }
2193     *pStream = This->stateBlock->streamSource[StreamNumber];
2194     *pStride = This->stateBlock->streamStride[StreamNumber];
2195     if (pOffset) {
2196         *pOffset = This->stateBlock->streamOffset[StreamNumber];
2197     }
2198
2199     if (*pStream != NULL) {
2200         IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2201     }
2202     return WINED3D_OK;
2203 }
2204
2205 /*Should be quite easy, just an extension of vertexdata
2206 ref...
2207 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2208
2209 The divider is a bit odd though
2210
2211 VertexOffset = StartVertex / Divider * StreamStride +
2212                VertexIndex / Divider * StreamStride + StreamOffset
2213
2214 */
2215 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
2216     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2217
2218     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2219     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
2220
2221     This->updateStateBlock->changed.streamFreq[StreamNumber]  = TRUE;
2222     This->updateStateBlock->set.streamFreq[StreamNumber]      = TRUE;
2223     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
2224
2225     if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2226         FIXME("Stream indexing not fully supported\n");
2227     }
2228
2229     return WINED3D_OK;
2230 }
2231
2232 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
2233     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2234
2235     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2236     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2237
2238     TRACE("(%p) : returning %d\n", This, *Divider);
2239
2240     return WINED3D_OK;
2241 }
2242
2243 /*****
2244  * Get / Set & Multiply Transform
2245  *****/
2246 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2247     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2248
2249     /* Most of this routine, comments included copied from ddraw tree initially: */
2250     TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2251
2252     /* Handle recording of state blocks */
2253     if (This->isRecordingState) {
2254         TRACE("Recording... not performing anything\n");
2255         This->updateStateBlock->changed.transform[d3dts] = TRUE;
2256         This->updateStateBlock->set.transform[d3dts]     = TRUE;
2257         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2258         return WINED3D_OK;
2259     }
2260
2261     /*
2262      * If the new matrix is the same as the current one,
2263      * we cut off any further processing. this seems to be a reasonable
2264      * optimization because as was noticed, some apps (warcraft3 for example)
2265      * tend towards setting the same matrix repeatedly for some reason.
2266      *
2267      * From here on we assume that the new matrix is different, wherever it matters.
2268      */
2269     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2270         TRACE("The app is setting the same matrix over again\n");
2271         return WINED3D_OK;
2272     } else {
2273         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2274     }
2275
2276     /*
2277        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2278        where ViewMat = Camera space, WorldMat = world space.
2279
2280        In OpenGL, camera and world space is combined into GL_MODELVIEW
2281        matrix.  The Projection matrix stay projection matrix.
2282      */
2283
2284     /* Capture the times we can just ignore the change for now */
2285     if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2286         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2287         /* Handled by the state manager */
2288     }
2289
2290     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2291     return WINED3D_OK;
2292
2293 }
2294 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2295     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2296     TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2297     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2298     return WINED3D_OK;
2299 }
2300
2301 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2302     WINED3DMATRIX *mat = NULL;
2303     WINED3DMATRIX temp;
2304
2305     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2306      * below means it will be recorded in a state block change, but it
2307      * works regardless where it is recorded.
2308      * If this is found to be wrong, change to StateBlock.
2309      */
2310     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2311     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2312
2313     if (State < HIGHEST_TRANSFORMSTATE)
2314     {
2315         mat = &This->updateStateBlock->transforms[State];
2316     } else {
2317         FIXME("Unhandled transform state!!\n");
2318     }
2319
2320     multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2321
2322     /* Apply change via set transform - will reapply to eg. lights this way */
2323     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2324 }
2325
2326 /*****
2327  * Get / Set Light
2328  *****/
2329 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2330    you can reference any indexes you want as long as that number max are enabled at any
2331    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2332    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2333    but when recording, just build a chain pretty much of commands to be replayed.                  */
2334
2335 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2336     float rho;
2337     PLIGHTINFOEL *object, *temp;
2338
2339     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2340     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2341
2342     /* If recording state block, just add to end of lights chain */
2343     if (This->isRecordingState) {
2344         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2345         if (NULL == object) {
2346             return WINED3DERR_OUTOFVIDEOMEMORY;
2347         }
2348         memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2349         object->OriginalIndex = Index;
2350         object->glIndex = -1;
2351         object->changed = TRUE;
2352
2353         /* Add to the END of the chain of lights changes to be replayed */
2354         if (This->updateStateBlock->lights == NULL) {
2355             This->updateStateBlock->lights = object;
2356         } else {
2357             temp = This->updateStateBlock->lights;
2358             while (temp->next != NULL) temp=temp->next;
2359             temp->next = object;
2360         }
2361         TRACE("Recording... not performing anything more\n");
2362         return WINED3D_OK;
2363     }
2364
2365     /* Ok, not recording any longer so do real work */
2366     object = This->stateBlock->lights;
2367     while (object != NULL && object->OriginalIndex != Index) object = object->next;
2368
2369     /* If we didn't find it in the list of lights, time to add it */
2370     if (object == NULL) {
2371         PLIGHTINFOEL *insertAt,*prevPos;
2372
2373         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2374         if (NULL == object) {
2375             return WINED3DERR_OUTOFVIDEOMEMORY;
2376         }
2377         object->OriginalIndex = Index;
2378         object->glIndex = -1;
2379
2380         /* Add it to the front of list with the idea that lights will be changed as needed
2381            BUT after any lights currently assigned GL indexes                             */
2382         insertAt = This->stateBlock->lights;
2383         prevPos  = NULL;
2384         while (insertAt != NULL && insertAt->glIndex != -1) {
2385             prevPos  = insertAt;
2386             insertAt = insertAt->next;
2387         }
2388
2389         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2390             This->stateBlock->lights = object;
2391         } else if (insertAt == NULL) { /* End of list */
2392             prevPos->next = object;
2393             object->prev = prevPos;
2394         } else { /* Middle of chain */
2395             if (prevPos == NULL) {
2396                 This->stateBlock->lights = object;
2397             } else {
2398                 prevPos->next = object;
2399             }
2400             object->prev = prevPos;
2401             object->next = insertAt;
2402             insertAt->prev = object;
2403         }
2404     }
2405
2406     /* Initialize the object */
2407     TRACE("Light %d setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2408           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2409           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2410           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2411     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2412           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2413     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2414
2415     /* Save away the information */
2416     memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2417
2418     switch (pLight->Type) {
2419     case WINED3DLIGHT_POINT:
2420         /* Position */
2421         object->lightPosn[0] = pLight->Position.x;
2422         object->lightPosn[1] = pLight->Position.y;
2423         object->lightPosn[2] = pLight->Position.z;
2424         object->lightPosn[3] = 1.0f;
2425         object->cutoff = 180.0f;
2426         /* FIXME: Range */
2427         break;
2428
2429     case WINED3DLIGHT_DIRECTIONAL:
2430         /* Direction */
2431         object->lightPosn[0] = -pLight->Direction.x;
2432         object->lightPosn[1] = -pLight->Direction.y;
2433         object->lightPosn[2] = -pLight->Direction.z;
2434         object->lightPosn[3] = 0.0;
2435         object->exponent     = 0.0f;
2436         object->cutoff       = 180.0f;
2437         break;
2438
2439     case WINED3DLIGHT_SPOT:
2440         /* Position */
2441         object->lightPosn[0] = pLight->Position.x;
2442         object->lightPosn[1] = pLight->Position.y;
2443         object->lightPosn[2] = pLight->Position.z;
2444         object->lightPosn[3] = 1.0;
2445
2446         /* Direction */
2447         object->lightDirn[0] = pLight->Direction.x;
2448         object->lightDirn[1] = pLight->Direction.y;
2449         object->lightDirn[2] = pLight->Direction.z;
2450         object->lightDirn[3] = 1.0;
2451
2452         /*
2453          * opengl-ish and d3d-ish spot lights use too different models for the
2454          * light "intensity" as a function of the angle towards the main light direction,
2455          * so we only can approximate very roughly.
2456          * however spot lights are rather rarely used in games (if ever used at all).
2457          * furthermore if still used, probably nobody pays attention to such details.
2458          */
2459         if (pLight->Falloff == 0) {
2460             rho = 6.28f;
2461         } else {
2462             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2463         }
2464         if (rho < 0.0001) rho = 0.0001f;
2465         object->exponent = -0.3/log(cos(rho/2));
2466         if (object->exponent > 128.0) {
2467                 object->exponent = 128.0;
2468         }
2469         object->cutoff = pLight->Phi*90/M_PI;
2470
2471         /* FIXME: Range */
2472         break;
2473
2474     default:
2475         FIXME("Unrecognized light type %d\n", pLight->Type);
2476     }
2477
2478     /* Update the live definitions if the light is currently assigned a glIndex */
2479     if (object->glIndex != -1) {
2480         setup_light(iface, object->glIndex, object);
2481     }
2482     return WINED3D_OK;
2483 }
2484
2485 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2486     PLIGHTINFOEL *lightInfo = NULL;
2487     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2488     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2489
2490     /* Locate the light in the live lights */
2491     lightInfo = This->stateBlock->lights;
2492     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2493
2494     if (lightInfo == NULL) {
2495         TRACE("Light information requested but light not defined\n");
2496         return WINED3DERR_INVALIDCALL;
2497     }
2498
2499     memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2500     return WINED3D_OK;
2501 }
2502
2503 /*****
2504  * Get / Set Light Enable
2505  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2506  *****/
2507 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2508     PLIGHTINFOEL *lightInfo = NULL;
2509     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2510     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2511
2512     /* Tests show true = 128...not clear why */
2513
2514     Enable = Enable? 128: 0;
2515
2516     /* If recording state block, just add to end of lights chain with changedEnable set to true */
2517     if (This->isRecordingState) {
2518         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2519         if (NULL == lightInfo) {
2520             return WINED3DERR_OUTOFVIDEOMEMORY;
2521         }
2522         lightInfo->OriginalIndex = Index;
2523         lightInfo->glIndex = -1;
2524         lightInfo->enabledChanged = TRUE;
2525         lightInfo->lightEnabled = Enable;
2526
2527         /* Add to the END of the chain of lights changes to be replayed */
2528         if (This->updateStateBlock->lights == NULL) {
2529             This->updateStateBlock->lights = lightInfo;
2530         } else {
2531             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2532             while (temp->next != NULL) temp=temp->next;
2533             temp->next = lightInfo;
2534         }
2535         TRACE("Recording... not performing anything more\n");
2536         return WINED3D_OK;
2537     }
2538
2539     /* Not recording... So, locate the light in the live lights */
2540     lightInfo = This->stateBlock->lights;
2541     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2542
2543     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2544     if (lightInfo == NULL) {
2545
2546         TRACE("Light enabled requested but light not defined, so defining one!\n");
2547         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2548
2549         /* Search for it again! Should be fairly quick as near head of list */
2550         lightInfo = This->stateBlock->lights;
2551         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2552         if (lightInfo == NULL) {
2553             FIXME("Adding default lights has failed dismally\n");
2554             return WINED3DERR_INVALIDCALL;
2555         }
2556     }
2557
2558     /* OK, we now have a light... */
2559     if (!Enable) {
2560
2561         /* If we are disabling it, check it was enabled, and
2562            still only do something if it has assigned a glIndex (which it should have!)   */
2563         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2564             TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2565             ENTER_GL();
2566             glDisable(GL_LIGHT0 + lightInfo->glIndex);
2567             checkGLcall("glDisable GL_LIGHT0+Index");
2568             LEAVE_GL();
2569         } else {
2570             TRACE("Nothing to do as light was not enabled\n");
2571         }
2572         lightInfo->lightEnabled = Enable;
2573     } else {
2574
2575         /* We are enabling it. If it is enabled, it's really simple */
2576         if (lightInfo->lightEnabled) {
2577             /* nop */
2578             TRACE("Nothing to do as light was enabled\n");
2579
2580         /* If it already has a glIndex, it's still simple */
2581         } else if (lightInfo->glIndex != -1) {
2582             TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2583             lightInfo->lightEnabled = Enable;
2584             ENTER_GL();
2585             glEnable(GL_LIGHT0 + lightInfo->glIndex);
2586             checkGLcall("glEnable GL_LIGHT0+Index already setup");
2587             LEAVE_GL();
2588
2589         /* Otherwise got to find space - lights are ordered gl indexes first */
2590         } else {
2591             PLIGHTINFOEL *bsf  = NULL;
2592             PLIGHTINFOEL *pos  = This->stateBlock->lights;
2593             PLIGHTINFOEL *prev = NULL;
2594             int           Index= 0;
2595             int           glIndex = -1;
2596
2597             /* Try to minimize changes as much as possible */
2598             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2599
2600                 /* Try to remember which index can be replaced if necessary */
2601                 if (bsf==NULL && !pos->lightEnabled) {
2602                     /* Found a light we can replace, save as best replacement */
2603                     bsf = pos;
2604                 }
2605
2606                 /* Step to next space */
2607                 prev = pos;
2608                 pos = pos->next;
2609                 Index ++;
2610             }
2611
2612             /* If we have too many active lights, fail the call */
2613             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2614                 FIXME("Program requests too many concurrent lights.\n");
2615                 return WINED3DERR_INVALIDCALL;
2616
2617             /* If we have allocated all lights, but not all are enabled,
2618                reuse one which is not enabled                           */
2619             } else if (Index == This->maxConcurrentLights) {
2620                 /* use bsf - Simply swap the new light and the BSF one */
2621                 PLIGHTINFOEL *bsfNext = bsf->next;
2622                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2623
2624                 /* Sort out ends */
2625                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2626                 if (bsf->prev != NULL) {
2627                     bsf->prev->next = lightInfo;
2628                 } else {
2629                     This->stateBlock->lights = lightInfo;
2630                 }
2631
2632                 /* If not side by side, lots of chains to update */
2633                 if (bsf->next != lightInfo) {
2634                     lightInfo->prev->next = bsf;
2635                     bsf->next->prev = lightInfo;
2636                     bsf->next       = lightInfo->next;
2637                     bsf->prev       = lightInfo->prev;
2638                     lightInfo->next = bsfNext;
2639                     lightInfo->prev = bsfPrev;
2640
2641                 } else {
2642                     /* Simple swaps */
2643                     bsf->prev = lightInfo;
2644                     bsf->next = lightInfo->next;
2645                     lightInfo->next = bsf;
2646                     lightInfo->prev = bsfPrev;
2647                 }
2648
2649
2650                 /* Update states */
2651                 glIndex = bsf->glIndex;
2652                 bsf->glIndex = -1;
2653                 lightInfo->glIndex = glIndex;
2654                 lightInfo->lightEnabled = Enable;
2655
2656                 /* Finally set up the light in gl itself */
2657                 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
2658                 ENTER_GL();
2659                 setup_light(iface, glIndex, lightInfo);
2660                 glEnable(GL_LIGHT0 + glIndex);
2661                 checkGLcall("glEnable GL_LIGHT0 new setup");
2662                 LEAVE_GL();
2663
2664             /* If we reached the end of the allocated lights, with space in the
2665                gl lights, setup a new light                                     */
2666             } else if (pos->glIndex == -1) {
2667
2668                 /* We reached the end of the allocated gl lights, so already
2669                     know the index of the next one!                          */
2670                 glIndex = Index;
2671                 lightInfo->glIndex = glIndex;
2672                 lightInfo->lightEnabled = Enable;
2673
2674                 /* In an ideal world, it's already in the right place */
2675                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2676                    /* No need to move it */
2677                 } else {
2678                     /* Remove this light from the list */
2679                     lightInfo->prev->next = lightInfo->next;
2680                     if (lightInfo->next != NULL) {
2681                         lightInfo->next->prev = lightInfo->prev;
2682                     }
2683
2684                     /* Add in at appropriate place (inbetween prev and pos) */
2685                     lightInfo->prev = prev;
2686                     lightInfo->next = pos;
2687                     if (prev == NULL) {
2688                         This->stateBlock->lights = lightInfo;
2689                     } else {
2690                         prev->next = lightInfo;
2691                     }
2692                     if (pos != NULL) {
2693                         pos->prev = lightInfo;
2694                     }
2695                 }
2696
2697                 /* Finally set up the light in gl itself */
2698                 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
2699                 ENTER_GL();
2700                 setup_light(iface, glIndex, lightInfo);
2701                 glEnable(GL_LIGHT0 + glIndex);
2702                 checkGLcall("glEnable GL_LIGHT0 new setup");
2703                 LEAVE_GL();
2704
2705             }
2706         }
2707     }
2708     return WINED3D_OK;
2709 }
2710
2711 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2712
2713     PLIGHTINFOEL *lightInfo = NULL;
2714     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2715     TRACE("(%p) : for idx(%d)\n", This, Index);
2716
2717     /* Locate the light in the live lights */
2718     lightInfo = This->stateBlock->lights;
2719     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2720
2721     if (lightInfo == NULL) {
2722         TRACE("Light enabled state requested but light not defined\n");
2723         return WINED3DERR_INVALIDCALL;
2724     }
2725     *pEnable = lightInfo->lightEnabled;
2726     return WINED3D_OK;
2727 }
2728
2729 /*****
2730  * Get / Set Clip Planes
2731  *****/
2732 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2733     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2734     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
2735
2736     /* Validate Index */
2737     if (Index >= GL_LIMITS(clipplanes)) {
2738         TRACE("Application has requested clipplane this device doesn't support\n");
2739         return WINED3DERR_INVALIDCALL;
2740     }
2741
2742     This->updateStateBlock->changed.clipplane[Index] = TRUE;
2743     This->updateStateBlock->set.clipplane[Index] = TRUE;
2744     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2745     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2746     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2747     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2748
2749     /* Handle recording of state blocks */
2750     if (This->isRecordingState) {
2751         TRACE("Recording... not performing anything\n");
2752         return WINED3D_OK;
2753     }
2754
2755     /* Apply it */
2756
2757     ENTER_GL();
2758
2759     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2760     glMatrixMode(GL_MODELVIEW);
2761     glPushMatrix();
2762     glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2763
2764     TRACE("Clipplane [%f,%f,%f,%f]\n",
2765           This->updateStateBlock->clipplane[Index][0],
2766           This->updateStateBlock->clipplane[Index][1],
2767           This->updateStateBlock->clipplane[Index][2],
2768           This->updateStateBlock->clipplane[Index][3]);
2769     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2770     checkGLcall("glClipPlane");
2771
2772     glPopMatrix();
2773     LEAVE_GL();
2774
2775     return WINED3D_OK;
2776 }
2777
2778 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2779     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2780     TRACE("(%p) : for idx %d\n", This, Index);
2781
2782     /* Validate Index */
2783     if (Index >= GL_LIMITS(clipplanes)) {
2784         TRACE("Application has requested clipplane this device doesn't support\n");
2785         return WINED3DERR_INVALIDCALL;
2786     }
2787
2788     pPlane[0] = This->stateBlock->clipplane[Index][0];
2789     pPlane[1] = This->stateBlock->clipplane[Index][1];
2790     pPlane[2] = This->stateBlock->clipplane[Index][2];
2791     pPlane[3] = This->stateBlock->clipplane[Index][3];
2792     return WINED3D_OK;
2793 }
2794
2795 /*****
2796  * Get / Set Clip Plane Status
2797  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2798  *****/
2799 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2800     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2801     FIXME("(%p) : stub\n", This);
2802     if (NULL == pClipStatus) {
2803       return WINED3DERR_INVALIDCALL;
2804     }
2805     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2806     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2807     return WINED3D_OK;
2808 }
2809
2810 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2811     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2812     FIXME("(%p) : stub\n", This);
2813     if (NULL == pClipStatus) {
2814       return WINED3DERR_INVALIDCALL;
2815     }
2816     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2817     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2818     return WINED3D_OK;
2819 }
2820
2821 /*****
2822  * Get / Set Material
2823  *****/
2824 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2825     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2826
2827     This->updateStateBlock->changed.material = TRUE;
2828     This->updateStateBlock->set.material = TRUE;
2829     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2830
2831     /* Handle recording of state blocks */
2832     if (This->isRecordingState) {
2833         TRACE("Recording... not performing anything\n");
2834         return WINED3D_OK;
2835     }
2836
2837     ENTER_GL();
2838     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2839         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2840     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2841         pMaterial->Ambient.b, pMaterial->Ambient.a);
2842     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2843         pMaterial->Specular.b, pMaterial->Specular.a);
2844     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2845         pMaterial->Emissive.b, pMaterial->Emissive.a);
2846     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2847
2848     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2849     checkGLcall("glMaterialfv(GL_AMBIENT)");
2850     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2851     checkGLcall("glMaterialfv(GL_DIFFUSE)");
2852
2853     /* Only change material color if specular is enabled, otherwise it is set to black */
2854     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2855        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2856        checkGLcall("glMaterialfv(GL_SPECULAR");
2857     } else {
2858        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2859        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2860        checkGLcall("glMaterialfv(GL_SPECULAR");
2861     }
2862     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2863     checkGLcall("glMaterialfv(GL_EMISSION)");
2864     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2865     checkGLcall("glMaterialf(GL_SHININESS");
2866
2867     LEAVE_GL();
2868     return WINED3D_OK;
2869 }
2870
2871 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2872     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2873     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2874     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2875         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2876     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2877         pMaterial->Ambient.b, pMaterial->Ambient.a);
2878     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2879         pMaterial->Specular.b, pMaterial->Specular.a);
2880     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2881         pMaterial->Emissive.b, pMaterial->Emissive.a);
2882     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2883
2884     return WINED3D_OK;
2885 }
2886
2887 /*****
2888  * Get / Set Indices
2889  *****/
2890 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2891                                              UINT BaseVertexIndex) {
2892     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
2893     IWineD3DIndexBuffer *oldIdxs;
2894     UINT oldBaseIndex = This->updateStateBlock->baseVertexIndex;
2895
2896     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2897     oldIdxs = This->updateStateBlock->pIndexData;
2898
2899     This->updateStateBlock->changed.indices = TRUE;
2900     This->updateStateBlock->set.indices = TRUE;
2901     This->updateStateBlock->pIndexData = pIndexData;
2902     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2903
2904     /* Handle recording of state blocks */
2905     if (This->isRecordingState) {
2906         TRACE("Recording... not performing anything\n");
2907         return WINED3D_OK;
2908     }
2909
2910     /* So far only the base vertex index is tracked */
2911     if(BaseVertexIndex != oldBaseIndex) {
2912         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2913     }
2914     return WINED3D_OK;
2915 }
2916
2917 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2918     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2919
2920     *ppIndexData = This->stateBlock->pIndexData;
2921
2922     /* up ref count on ppindexdata */
2923     if (*ppIndexData) {
2924         IWineD3DIndexBuffer_AddRef(*ppIndexData);
2925         *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2926         TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2927     }else{
2928         TRACE("(%p) No index data set\n", This);
2929     }
2930     TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2931
2932     return WINED3D_OK;
2933 }
2934
2935 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2936 static HRESULT WINAPI IWineD3DDeviceImpl_SetBasevertexIndex(IWineD3DDevice *iface, UINT BaseIndex) {
2937     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2938     TRACE("(%p)->(%d)\n", This, BaseIndex);
2939
2940     if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
2941         TRACE("Application is setting the old value over, nothing to do\n");
2942         return WINED3D_OK;
2943     }
2944
2945     This->updateStateBlock->baseVertexIndex = BaseIndex;
2946
2947     if (This->isRecordingState) {
2948         TRACE("Recording... not performing anything\n");
2949         return WINED3D_OK;
2950     }
2951     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2952     return WINED3D_OK;
2953 }
2954
2955 /*****
2956  * Get / Set Viewports
2957  *****/
2958 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2959     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2960
2961     TRACE("(%p)\n", This);
2962     This->updateStateBlock->changed.viewport = TRUE;
2963     This->updateStateBlock->set.viewport = TRUE;
2964     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2965
2966     /* Handle recording of state blocks */
2967     if (This->isRecordingState) {
2968         TRACE("Recording... not performing anything\n");
2969         return WINED3D_OK;
2970     }
2971
2972     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
2973           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2974
2975     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
2976     return WINED3D_OK;
2977
2978 }
2979
2980 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2981     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2982     TRACE("(%p)\n", This);
2983     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2984     return WINED3D_OK;
2985 }
2986
2987 /*****
2988  * Get / Set Render States
2989  * TODO: Verify against dx9 definitions
2990  *****/
2991 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
2992
2993     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
2994     DWORD oldValue = This->stateBlock->renderState[State];
2995
2996     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
2997
2998     This->updateStateBlock->changed.renderState[State] = TRUE;
2999     This->updateStateBlock->set.renderState[State] = TRUE;
3000     This->updateStateBlock->renderState[State] = Value;
3001
3002     /* Handle recording of state blocks */
3003     if (This->isRecordingState) {
3004         TRACE("Recording... not performing anything\n");
3005         return WINED3D_OK;
3006     }
3007
3008     /* Compared here and not before the assignment to allow proper stateblock recording */
3009     if(Value == oldValue) {
3010         TRACE("Application is setting the old value over, nothing to do\n");
3011     } else {
3012         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
3013     }
3014
3015     return WINED3D_OK;
3016 }
3017
3018 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
3019     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3020     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
3021     *pValue = This->stateBlock->renderState[State];
3022     return WINED3D_OK;
3023 }
3024
3025 /*****
3026  * Get / Set Sampler States
3027  * TODO: Verify against dx9 definitions
3028  *****/
3029
3030 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3031     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3032     DWORD oldValue = This->stateBlock->samplerState[Sampler][Type];
3033
3034     /**
3035     * SetSampler is designed to allow for more than the standard up to 8 textures
3036     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
3037     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3038     *
3039     * http://developer.nvidia.com/object/General_FAQ.html#t6
3040     *
3041     * There are two new settings for GForce
3042     * the sampler one:
3043     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3044     * and the texture one:
3045     * GL_MAX_TEXTURE_COORDS_ARB.
3046     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3047      ******************/
3048     /** NOTE: States are applied in IWineD3DBaseTextre ApplyStateChanges the sampler state handler**/
3049     if(Sampler >  GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3050          FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
3051             Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
3052         return WINED3DERR_INVALIDCALL;
3053     }
3054
3055     TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
3056         debug_d3dsamplerstate(Type), Type, Value);
3057     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
3058     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
3059     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3060
3061     /* Handle recording of state blocks */
3062     if (This->isRecordingState) {
3063         TRACE("Recording... not performing anything\n");
3064         return WINED3D_OK;
3065     }
3066
3067     if(oldValue == Value) {
3068         TRACE("Application is setting the old value over, nothing to do\n");
3069         return WINED3D_OK;
3070     }
3071
3072     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
3073
3074     return WINED3D_OK;
3075 }
3076
3077 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3078     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3079     /** TODO: check that sampler is in  range **/
3080     *Value = This->stateBlock->samplerState[Sampler][Type];
3081     TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
3082
3083     return WINED3D_OK;
3084 }
3085
3086 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3087     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3088     RECT windowRect;
3089     UINT winHeight;
3090
3091     This->updateStateBlock->set.scissorRect = TRUE;
3092     This->updateStateBlock->changed.scissorRect = TRUE;
3093     memcpy(&This->updateStateBlock->scissorRect, pRect, sizeof(*pRect));
3094
3095     if(This->isRecordingState) {
3096         TRACE("Recording... not performing anything\n");
3097         return WINED3D_OK;
3098     }
3099
3100     GetClientRect(((IWineD3DSwapChainImpl *)This->swapchains[0])->win_handle, &windowRect);
3101     /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3102     * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3103     */
3104     winHeight = windowRect.bottom - windowRect.top;
3105     TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->bottom - winHeight,
3106           pRect->right - pRect->left, pRect->bottom - pRect->top);
3107     ENTER_GL();
3108     glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3109     checkGLcall("glScissor");
3110     LEAVE_GL();
3111
3112     return WINED3D_OK;
3113 }
3114
3115 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3116     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3117
3118     memcpy(pRect, &This->updateStateBlock->scissorRect, sizeof(pRect));
3119     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3120     return WINED3D_OK;
3121 }
3122
3123 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3124     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3125     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3126
3127     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3128
3129     This->updateStateBlock->vertexDecl = pDecl;
3130     This->updateStateBlock->changed.vertexDecl = TRUE;
3131     This->updateStateBlock->set.vertexDecl = TRUE;
3132
3133     if (This->isRecordingState) {
3134         TRACE("Recording... not performing anything\n");
3135         return WINED3D_OK;
3136     } else if(pDecl == oldDecl) {
3137         /* Checked after the assignment to allow proper stateblock recording */
3138         TRACE("Application is setting the old declaration over, nothing to do\n");
3139         return WINED3D_OK;
3140     }
3141
3142     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
3143     return WINED3D_OK;
3144 }
3145
3146 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3147     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3148
3149     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3150
3151     *ppDecl = This->stateBlock->vertexDecl;
3152     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3153     return WINED3D_OK;
3154 }
3155
3156 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3157     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3158     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3159
3160     This->updateStateBlock->vertexShader         = pShader;
3161     This->updateStateBlock->changed.vertexShader = TRUE;
3162     This->updateStateBlock->set.vertexShader     = TRUE;
3163
3164     if (This->isRecordingState) {
3165         TRACE("Recording... not performing anything\n");
3166         return WINED3D_OK;
3167     } else if(oldShader == pShader) {
3168         /* Checked here to allow proper stateblock recording */
3169         TRACE("App is setting the old shader over, nothing to do\n");
3170         return WINED3D_OK;
3171     }
3172
3173     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3174
3175     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
3176
3177     return WINED3D_OK;
3178 }
3179
3180 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3181     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3182
3183     if (NULL == ppShader) {
3184         return WINED3DERR_INVALIDCALL;
3185     }
3186     *ppShader = This->stateBlock->vertexShader;
3187     if( NULL != *ppShader)
3188         IWineD3DVertexShader_AddRef(*ppShader);
3189
3190     TRACE("(%p) : returning %p\n", This, *ppShader);
3191     return WINED3D_OK;
3192 }
3193
3194 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
3195     IWineD3DDevice *iface,
3196     UINT start,
3197     CONST BOOL *srcData,
3198     UINT count) {
3199
3200     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3201     int i, cnt = min(count, MAX_CONST_B - start);
3202
3203     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3204             iface, srcData, start, count);
3205
3206     if (srcData == NULL || cnt < 0)
3207         return WINED3DERR_INVALIDCALL;
3208
3209     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3210     for (i = 0; i < cnt; i++)
3211         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3212
3213     for (i = start; i < cnt + start; ++i) {
3214         This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
3215         This->updateStateBlock->set.vertexShaderConstantsB[i]     = TRUE;
3216     }
3217
3218     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3219
3220     return WINED3D_OK;
3221 }
3222
3223 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
3224     IWineD3DDevice *iface,
3225     UINT start,
3226     BOOL *dstData,
3227     UINT count) {
3228
3229     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3230     int cnt = min(count, MAX_CONST_B - start);
3231
3232     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3233             iface, dstData, start, count);
3234
3235     if (dstData == NULL || cnt < 0)
3236         return WINED3DERR_INVALIDCALL;
3237
3238     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
3239     return WINED3D_OK;
3240 }
3241
3242 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
3243     IWineD3DDevice *iface,
3244     UINT start,
3245     CONST int *srcData,
3246     UINT count) {
3247
3248     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3249     int i, cnt = min(count, MAX_CONST_I - start);
3250
3251     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3252             iface, srcData, start, count);
3253
3254     if (srcData == NULL || cnt < 0)
3255         return WINED3DERR_INVALIDCALL;
3256
3257     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3258     for (i = 0; i < cnt; i++)
3259         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3260            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3261
3262     for (i = start; i < cnt + start; ++i) {
3263         This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
3264         This->updateStateBlock->set.vertexShaderConstantsI[i]     = TRUE;
3265     }
3266
3267     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3268
3269     return WINED3D_OK;
3270 }
3271
3272 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
3273     IWineD3DDevice *iface,
3274     UINT start,
3275     int *dstData,
3276     UINT count) {
3277
3278     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3279     int cnt = min(count, MAX_CONST_I - start);
3280
3281     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3282             iface, dstData, start, count);
3283
3284     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
3285         return WINED3DERR_INVALIDCALL;
3286
3287     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3288     return WINED3D_OK;
3289 }
3290
3291 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3292     IWineD3DDevice *iface,
3293     UINT start,
3294     CONST float *srcData,
3295     UINT count) {
3296
3297     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3298     int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3299
3300     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3301             iface, srcData, start, count);
3302
3303     if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
3304         return WINED3DERR_INVALIDCALL;
3305
3306     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
3307     for (i = 0; i < cnt; i++)
3308         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3309            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3310
3311     for (i = start; i < cnt + start; ++i) {
3312         if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
3313             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3314             ptr->idx = i;
3315             list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
3316             This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
3317         }
3318         This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
3319     }
3320
3321     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3322
3323     return WINED3D_OK;
3324 }
3325
3326 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3327     IWineD3DDevice *iface,
3328     UINT start,
3329     float *dstData,
3330     UINT count) {
3331
3332     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3333     int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3334
3335     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3336             iface, dstData, start, count);
3337
3338     if (dstData == NULL || cnt < 0)
3339         return WINED3DERR_INVALIDCALL;
3340
3341     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3342     return WINED3D_OK;
3343 }
3344
3345 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3346     DWORD i;
3347     for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
3348         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3349     }
3350 }
3351
3352 static void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3353     DWORD i, tex;
3354     /* This code can assume that GL_NV_register_combiners are supported, otherwise
3355      * it is never called.
3356      *
3357      * Rules are:
3358      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3359      * that would be really messy and require shader recompilation
3360      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3361      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3362      * -> Whith a 1:1 mapping oneToOneTexUnitMap is set to avoid checking MAX_SAMPLERS array
3363      * entries to make pixel shaders cheaper. MAX_SAMPLERS will be 128 in dx10
3364      */
3365     if(This->stateBlock->pixelShader || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) {
3366         if(This->oneToOneTexUnitMap) {
3367             TRACE("Not touching 1:1 map\n");
3368             return;
3369         }
3370         TRACE("Restoring 1:1 texture unit mapping\n");
3371         /* Restore a 1:1 mapping */
3372         for(i = 0; i < MAX_SAMPLERS; i++) {
3373             if(This->texUnitMap[i] != i) {
3374                 This->texUnitMap[i] = i;
3375                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3376                 markTextureStagesDirty(This, i);
3377             }
3378         }
3379         This->oneToOneTexUnitMap = TRUE;
3380         return;
3381     } else {
3382         /* No pixel shader, and we do not have enough texture units available. Try to skip NULL textures
3383          * First, see if we can succeed at all
3384          */
3385         tex = 0;
3386         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3387             if(This->stateBlock->textures[i] == NULL) tex++;
3388         }
3389
3390         if(GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) {
3391             FIXME("Too many bound textures to support the combiner settings\n");
3392             return;
3393         }
3394
3395         /* Now work out the mapping */
3396         tex = 0;
3397         This->oneToOneTexUnitMap = FALSE;
3398         WARN("Non 1:1 mapping UNTESTED!\n");
3399         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3400             /* Skip NULL textures */
3401             if (!This->stateBlock->textures[i]) {
3402                 /* Map to -1, so the check below doesn't fail if a non-NULL
3403                  * texture is set on this stage */
3404                 TRACE("Mapping texture stage %d to -1\n", i);
3405                 This->texUnitMap[i] = -1;
3406
3407                 continue;
3408             }
3409
3410             TRACE("Mapping texture stage %d to unit %d\n", i, tex);
3411             if(This->texUnitMap[i] != tex) {
3412                 This->texUnitMap[i] = tex;
3413                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3414                 markTextureStagesDirty(This, i);
3415             }
3416
3417             ++tex;
3418         }
3419     }
3420 }
3421
3422 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3423     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3424     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3425     This->updateStateBlock->pixelShader         = pShader;
3426     This->updateStateBlock->changed.pixelShader = TRUE;
3427     This->updateStateBlock->set.pixelShader     = TRUE;
3428
3429     /* Handle recording of state blocks */
3430     if (This->isRecordingState) {
3431         TRACE("Recording... not performing anything\n");
3432     }
3433
3434     if (This->isRecordingState) {
3435         TRACE("Recording... not performing anything\n");
3436         return WINED3D_OK;
3437     }
3438
3439     if(pShader == oldShader) {
3440         TRACE("App is setting the old pixel shader over, nothing to do\n");
3441         return WINED3D_OK;
3442     }
3443
3444     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3445     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3446
3447     /* Rebuild the texture unit mapping if nvrc's are supported */
3448     if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3449         IWineD3DDeviceImpl_FindTexUnitMap(This);
3450     }
3451
3452     return WINED3D_OK;
3453 }
3454
3455 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3456     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3457
3458     if (NULL == ppShader) {
3459         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3460         return WINED3DERR_INVALIDCALL;
3461     }
3462
3463     *ppShader =  This->stateBlock->pixelShader;
3464     if (NULL != *ppShader) {
3465         IWineD3DPixelShader_AddRef(*ppShader);
3466     }
3467     TRACE("(%p) : returning %p\n", This, *ppShader);
3468     return WINED3D_OK;
3469 }
3470
3471 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3472     IWineD3DDevice *iface,
3473     UINT start,
3474     CONST BOOL *srcData,
3475     UINT count) {
3476
3477     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3478     int i, cnt = min(count, MAX_CONST_B - start);
3479
3480     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3481             iface, srcData, start, count);
3482
3483     if (srcData == NULL || cnt < 0)
3484         return WINED3DERR_INVALIDCALL;
3485
3486     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3487     for (i = 0; i < cnt; i++)
3488         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3489
3490     for (i = start; i < cnt + start; ++i) {
3491         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3492         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
3493     }
3494
3495     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3496
3497     return WINED3D_OK;
3498 }
3499
3500 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3501     IWineD3DDevice *iface,
3502     UINT start,
3503     BOOL *dstData,
3504     UINT count) {
3505
3506     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3507     int cnt = min(count, MAX_CONST_B - start);
3508
3509     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3510             iface, dstData, start, count);
3511
3512     if (dstData == NULL || cnt < 0)
3513         return WINED3DERR_INVALIDCALL;
3514
3515     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3516     return WINED3D_OK;
3517 }
3518
3519 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3520     IWineD3DDevice *iface,
3521     UINT start,
3522     CONST int *srcData,
3523     UINT count) {
3524
3525     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3526     int i, cnt = min(count, MAX_CONST_I - start);
3527
3528     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3529             iface, srcData, start, count);
3530
3531     if (srcData == NULL || cnt < 0)
3532         return WINED3DERR_INVALIDCALL;
3533
3534     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3535     for (i = 0; i < cnt; i++)
3536         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3537            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3538
3539     for (i = start; i < cnt + start; ++i) {
3540         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3541         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
3542     }
3543
3544     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3545
3546     return WINED3D_OK;
3547 }
3548
3549 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3550     IWineD3DDevice *iface,
3551     UINT start,
3552     int *dstData,
3553     UINT count) {
3554
3555     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3556     int cnt = min(count, MAX_CONST_I - start);
3557
3558     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3559             iface, dstData, start, count);
3560
3561     if (dstData == NULL || cnt < 0)
3562         return WINED3DERR_INVALIDCALL;
3563
3564     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3565     return WINED3D_OK;
3566 }
3567
3568 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3569     IWineD3DDevice *iface,
3570     UINT start,
3571     CONST float *srcData,
3572     UINT count) {
3573
3574     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3575     int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3576
3577     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3578             iface, srcData, start, count);
3579
3580     if (srcData == NULL || cnt < 0)
3581         return WINED3DERR_INVALIDCALL;
3582
3583     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
3584     for (i = 0; i < cnt; i++)
3585         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3586            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3587
3588     for (i = start; i < cnt + start; ++i) {
3589         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3590             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3591             ptr->idx = i;
3592             list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3593             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3594         }
3595         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3596     }
3597
3598     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3599
3600     return WINED3D_OK;
3601 }
3602
3603 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3604     IWineD3DDevice *iface,
3605     UINT start,
3606     float *dstData,
3607     UINT count) {
3608
3609     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3610     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3611
3612     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3613             iface, dstData, start, count);
3614
3615     if (dstData == NULL || cnt < 0)
3616         return WINED3DERR_INVALIDCALL;
3617
3618     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3619     return WINED3D_OK;
3620 }
3621
3622 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3623 static HRESULT
3624 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3625     char *dest_ptr, *dest_conv = NULL;
3626     unsigned int i;
3627     DWORD DestFVF = dest->fvf;
3628     WINED3DVIEWPORT vp;
3629     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3630     BOOL doClip;
3631     int numTextures;
3632
3633     if (SrcFVF & WINED3DFVF_NORMAL) {
3634         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3635     }
3636
3637     if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
3638         ERR("Source has no position mask\n");
3639         return WINED3DERR_INVALIDCALL;
3640     }
3641
3642     /* We might access VBOs from this code, so hold the lock */
3643     ENTER_GL();
3644
3645     if (dest->resource.allocatedMemory == NULL) {
3646         /* This may happen if we do direct locking into a vbo. Unlikely,
3647          * but theoretically possible(ddraw processvertices test)
3648          */
3649         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3650         if(!dest->resource.allocatedMemory) {
3651             LEAVE_GL();
3652             ERR("Out of memory\n");
3653             return E_OUTOFMEMORY;
3654         }
3655         if(dest->vbo) {
3656             void *src;
3657             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3658             checkGLcall("glBindBufferARB");
3659             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3660             if(src) {
3661                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3662             }
3663             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3664             checkGLcall("glUnmapBufferARB");
3665         }
3666     }
3667
3668     /* Get a pointer into the destination vbo(create one if none exists) and
3669      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3670      */
3671     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3672         CreateVBO(dest);
3673     }
3674
3675     if(dest->vbo) {
3676         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3677         dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
3678         if(!dest_conv) {
3679             ERR("glMapBuffer failed\n");
3680             /* Continue without storing converted vertices */
3681         }
3682     }
3683
3684     /* Should I clip?
3685      * a) WINED3DRS_CLIPPING is enabled
3686      * b) WINED3DVOP_CLIP is passed
3687      */
3688     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3689         static BOOL warned = FALSE;
3690         /*
3691          * The clipping code is not quite correct. Some things need
3692          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3693          * so disable clipping for now.
3694          * (The graphics in Half-Life are broken, and my processvertices
3695          *  test crashes with IDirect3DDevice3)
3696         doClip = TRUE;
3697          */
3698         doClip = FALSE;
3699         if(!warned) {
3700            warned = TRUE;
3701            FIXME("Clipping is broken and disabled for now\n");
3702         }
3703     } else doClip = FALSE;
3704     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3705     if(dest_conv) {
3706         dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3707     }
3708
3709     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3710                                  WINED3DTS_VIEW,
3711                                  &view_mat);
3712     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3713                                  WINED3DTS_PROJECTION,
3714                                  &proj_mat);
3715     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3716                                  WINED3DTS_WORLDMATRIX(0),
3717                                  &world_mat);
3718
3719     TRACE("View mat:\n");
3720     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);
3721     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);
3722     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);
3723     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);
3724
3725     TRACE("Proj mat:\n");
3726     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);
3727     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);
3728     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);
3729     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);
3730
3731     TRACE("World mat:\n");
3732     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);
3733     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);
3734     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);
3735     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);
3736
3737     /* Get the viewport */
3738     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3739     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3740           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3741
3742     multiply_matrix(&mat,&view_mat,&world_mat);
3743     multiply_matrix(&mat,&proj_mat,&mat);
3744
3745     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3746
3747     for (i = 0; i < dwCount; i+= 1) {
3748         unsigned int tex_index;
3749
3750         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3751              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3752             /* The position first */
3753             float *p =
3754               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3755             float x, y, z, rhw;
3756             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3757
3758             /* Multiplication with world, view and projection matrix */
3759             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);
3760             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);
3761             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);
3762             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);
3763
3764             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3765
3766             /* WARNING: The following things are taken from d3d7 and were not yet checked
3767              * against d3d8 or d3d9!
3768              */
3769
3770             /* Clipping conditions: From
3771              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
3772              *
3773              * A vertex is clipped if it does not match the following requirements
3774              * -rhw < x <= rhw
3775              * -rhw < y <= rhw
3776              *    0 < z <= rhw
3777              *    0 < rhw ( Not in d3d7, but tested in d3d7)
3778              *
3779              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3780              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3781              *
3782              */
3783
3784             if( !doClip ||
3785                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3786                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
3787                   ( rhw > eps ) ) ) {
3788
3789                 /* "Normal" viewport transformation (not clipped)
3790                  * 1) The values are divided by rhw
3791                  * 2) The y axis is negative, so multiply it with -1
3792                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3793                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3794                  * 4) Multiply x with Width/2 and add Width/2
3795                  * 5) The same for the height
3796                  * 6) Add the viewpoint X and Y to the 2D coordinates and
3797                  *    The minimum Z value to z
3798                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3799                  *
3800                  * Well, basically it's simply a linear transformation into viewport
3801                  * coordinates
3802                  */
3803
3804                 x /= rhw;
3805                 y /= rhw;
3806                 z /= rhw;
3807
3808                 y *= -1;
3809
3810                 x *= vp.Width / 2;
3811                 y *= vp.Height / 2;
3812                 z *= vp.MaxZ - vp.MinZ;
3813
3814                 x += vp.Width / 2 + vp.X;
3815                 y += vp.Height / 2 + vp.Y;
3816                 z += vp.MinZ;
3817
3818                 rhw = 1 / rhw;
3819             } else {
3820                 /* That vertex got clipped
3821                  * Contrary to OpenGL it is not dropped completely, it just
3822                  * undergoes a different calculation.
3823                  */
3824                 TRACE("Vertex got clipped\n");
3825                 x += rhw;
3826                 y += rhw;
3827
3828                 x  /= 2;
3829                 y  /= 2;
3830
3831                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3832                  * outside of the main vertex buffer memory. That needs some more
3833                  * investigation...
3834                  */
3835             }
3836
3837             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3838
3839
3840             ( (float *) dest_ptr)[0] = x;
3841             ( (float *) dest_ptr)[1] = y;
3842             ( (float *) dest_ptr)[2] = z;
3843             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3844
3845             dest_ptr += 3 * sizeof(float);
3846
3847             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3848                 dest_ptr += sizeof(float);
3849             }
3850
3851             if(dest_conv) {
3852                 float w = 1 / rhw;
3853                 ( (float *) dest_conv)[0] = x * w;
3854                 ( (float *) dest_conv)[1] = y * w;
3855                 ( (float *) dest_conv)[2] = z * w;
3856                 ( (float *) dest_conv)[3] = w;
3857
3858                 dest_conv += 3 * sizeof(float);
3859
3860                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3861                     dest_conv += sizeof(float);
3862                 }
3863             }
3864         }
3865         if (DestFVF & WINED3DFVF_PSIZE) {
3866             dest_ptr += sizeof(DWORD);
3867             if(dest_conv) dest_conv += sizeof(DWORD);
3868         }
3869         if (DestFVF & WINED3DFVF_NORMAL) {
3870             float *normal =
3871               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
3872             /* AFAIK this should go into the lighting information */
3873             FIXME("Didn't expect the destination to have a normal\n");
3874             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3875             if(dest_conv) {
3876                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3877             }
3878         }
3879
3880         if (DestFVF & WINED3DFVF_DIFFUSE) {
3881             DWORD *color_d = 
3882               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
3883             if(!color_d) {
3884                 static BOOL warned = FALSE;
3885
3886                 if(!warned) {
3887                     ERR("No diffuse color in source, but destination has one\n");
3888                     warned = TRUE;
3889                 }
3890
3891                 *( (DWORD *) dest_ptr) = 0xffffffff;
3892                 dest_ptr += sizeof(DWORD);
3893
3894                 if(dest_conv) {
3895                     *( (DWORD *) dest_conv) = 0xffffffff;
3896                     dest_conv += sizeof(DWORD);
3897                 }
3898             }
3899             else {
3900                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3901                 if(dest_conv) {
3902                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
3903                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3904                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3905                     dest_conv += sizeof(DWORD);
3906                 }
3907             }
3908         }
3909
3910         if (DestFVF & WINED3DFVF_SPECULAR) { 
3911             /* What's the color value in the feedback buffer? */
3912             DWORD *color_s = 
3913               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
3914             if(!color_s) {
3915                 static BOOL warned = FALSE;
3916
3917                 if(!warned) {
3918                     ERR("No specular color in source, but destination has one\n");
3919                     warned = TRUE;
3920                 }
3921
3922                 *( (DWORD *) dest_ptr) = 0xFF000000;
3923                 dest_ptr += sizeof(DWORD);
3924
3925                 if(dest_conv) {
3926                     *( (DWORD *) dest_conv) = 0xFF000000;
3927                     dest_conv += sizeof(DWORD);
3928                 }
3929             }
3930             else {
3931                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3932                 if(dest_conv) {
3933                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
3934                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
3935                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
3936                     dest_conv += sizeof(DWORD);
3937                 }
3938             }
3939         }
3940
3941         for (tex_index = 0; tex_index < numTextures; tex_index++) {
3942             float *tex_coord =
3943               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
3944                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
3945             if(!tex_coord) {
3946                 ERR("No source texture, but destination requests one\n");
3947                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3948                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3949             }
3950             else {
3951                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3952                 if(dest_conv) {
3953                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3954                 }
3955             }
3956         }
3957     }
3958
3959     if(dest_conv) {
3960         GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3961         checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
3962     }
3963
3964     LEAVE_GL();
3965
3966     return WINED3D_OK;
3967 }
3968 #undef copy_and_next
3969
3970 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3971     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3972     IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
3973     WineDirect3DVertexStridedData strided;
3974     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
3975
3976     if (!SrcImpl) {
3977         WARN("NULL source vertex buffer\n");
3978         return WINED3DERR_INVALIDCALL;
3979     }
3980     /* We don't need the source vbo because this buffer is only used as
3981      * a source for ProcessVertices. Avoid wasting resources by converting the
3982      * buffer and loading the VBO
3983      */
3984     if(SrcImpl->vbo) {
3985         TRACE("Releasing the source vbo, it won't be needed\n");
3986
3987         if(!SrcImpl->resource.allocatedMemory) {
3988             /* Rescue the data from the buffer */
3989             void *src;
3990             SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
3991             if(!SrcImpl->resource.allocatedMemory) {
3992                 ERR("Out of memory\n");
3993                 return E_OUTOFMEMORY;
3994             }
3995
3996             ENTER_GL();
3997             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
3998             checkGLcall("glBindBufferARB");
3999
4000             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
4001             if(src) {
4002                 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
4003             }
4004
4005             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4006             checkGLcall("glUnmapBufferARB");
4007         } else {
4008             ENTER_GL();
4009         }
4010
4011         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
4012         checkGLcall("glBindBufferARB");
4013         GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
4014         checkGLcall("glDeleteBuffersARB");
4015         LEAVE_GL();
4016
4017         SrcImpl->vbo = 0;
4018     }
4019
4020     memset(&strided, 0, sizeof(strided));
4021     primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0, 0);
4022
4023     return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4024 }
4025
4026 /*****
4027  * Get / Set Texture Stage States
4028  * TODO: Verify against dx9 definitions
4029  *****/
4030 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4031     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4032     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
4033
4034     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4035
4036     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4037
4038     /* Reject invalid texture units */
4039     if (Stage >= GL_LIMITS(texture_stages)) {
4040         TRACE("Attempt to access invalid texture rejected\n");
4041         return WINED3DERR_INVALIDCALL;
4042     }
4043
4044     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4045     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
4046     This->updateStateBlock->textureState[Stage][Type]         = Value;
4047
4048     if (This->isRecordingState) {
4049         TRACE("Recording... not performing anything\n");
4050         return WINED3D_OK;
4051     }
4052
4053     /* Checked after the assignments to allow proper stateblock recording */
4054     if(oldValue == Value) {
4055         TRACE("App is setting the old value over, nothing to do\n");
4056         return WINED3D_OK;
4057     }
4058
4059     if(Stage > This->stateBlock->lowest_disabled_stage &&
4060        StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
4061         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4062          * Changes in other states are important on disabled stages too
4063          */
4064         return WINED3D_OK;
4065     }
4066
4067     if(Type == WINED3DTSS_COLOROP) {
4068         int i;
4069
4070         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
4071             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4072              * they have to be disabled
4073              *
4074              * The current stage is dirtified below.
4075              */
4076             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
4077                 TRACE("Additionally dirtifying stage %d\n", i);
4078                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4079             }
4080             This->stateBlock->lowest_disabled_stage = Stage;
4081             TRACE("New lowest disabled: %d\n", Stage);
4082         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
4083             /* Previously disabled stage enabled. Stages above it may need enabling
4084              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4085              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4086              *
4087              * Again stage Stage doesn't need to be dirtified here, it is handled below.
4088              */
4089
4090             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
4091                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
4092                     break;
4093                 }
4094                 TRACE("Additionally dirtifying stage %d due to enable\n", i);
4095                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4096             }
4097             This->stateBlock->lowest_disabled_stage = i;
4098             TRACE("New lowest disabled: %d\n", i);
4099         }
4100         if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4101             /* TODO: Built a stage -> texture unit mapping for register combiners */
4102         }
4103     }
4104
4105     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
4106
4107     /* Rebuild the stage -> gl texture unit mapping if register combiners are supported
4108      * If there is a pixel shader there will be a 1:1 mapping, no need to touch it. SetPixelShader
4109      * will call FindTexUnitMap too.
4110      */
4111     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4112         IWineD3DDeviceImpl_FindTexUnitMap(This);
4113     }
4114     return WINED3D_OK;
4115 }
4116
4117 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4118     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4119     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4120     *pValue = This->updateStateBlock->textureState[Stage][Type];
4121     return WINED3D_OK;
4122 }
4123
4124 /*****
4125  * Get / Set Texture
4126  *****/
4127 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4128
4129     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4130     IWineD3DBaseTexture   *oldTexture;
4131
4132     oldTexture = This->updateStateBlock->textures[Stage];
4133     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
4134
4135 #if 0 /* TODO: check so vertex textures */
4136     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4137         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4138         return WINED3D_OK;
4139     }
4140 #endif
4141
4142     /* Reject invalid texture units */
4143     if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
4144         WARN("Attempt to access invalid texture rejected\n");
4145         return WINED3DERR_INVALIDCALL;
4146     }
4147
4148     if(pTexture != NULL) {
4149         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
4150          */
4151         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
4152             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4153             return WINED3DERR_INVALIDCALL;
4154         }
4155         This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
4156     }
4157
4158     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
4159     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4160
4161     This->updateStateBlock->set.textures[Stage]     = TRUE;
4162     This->updateStateBlock->changed.textures[Stage] = TRUE;
4163     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4164     This->updateStateBlock->textures[Stage]         = pTexture;
4165
4166     /* Handle recording of state blocks */
4167     if (This->isRecordingState) {
4168         TRACE("Recording... not performing anything\n");
4169         return WINED3D_OK;
4170     }
4171
4172     if(oldTexture == pTexture) {
4173         TRACE("App is setting the same texture again, nothing to do\n");
4174         return WINED3D_OK;
4175     }
4176
4177     /** NOTE: MSDN says that setTexture increases the reference count,
4178     * and the the application nust set the texture back to null (or have a leaky application),
4179     * This means we should pass the refcount up to the parent
4180      *******************************/
4181     if (NULL != This->updateStateBlock->textures[Stage]) {
4182         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
4183         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
4184
4185         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4186         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
4187             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4188              * so the COLOROP and ALPHAOP have to be dirtified.
4189              */
4190             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4191             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4192         }
4193         if(bindCount == 1) {
4194             new->baseTexture.sampler = Stage;
4195         }
4196         /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
4197
4198     }
4199
4200     if (NULL != oldTexture) {
4201         IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
4202         LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
4203
4204         IWineD3DBaseTexture_Release(oldTexture);
4205         if(pTexture == NULL && Stage < MAX_TEXTURES) {
4206             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4207             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4208         }
4209
4210         if(bindCount && old->baseTexture.sampler == Stage) {
4211             int i;
4212             /* Have to do a search for the other sampler(s) where the texture is bound to
4213              * Shouldn't happen as long as apps bind a texture only to one stage
4214              */
4215             TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
4216             for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
4217                 if(This->updateStateBlock->textures[i] == oldTexture) {
4218                     old->baseTexture.sampler = i;
4219                     break;
4220                 }
4221             }
4222         }
4223     }
4224
4225     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
4226
4227     /* Verify the texture unit mapping(and rebuild it if needed) if we use nvrcs and no
4228      * pixel shader is used
4229      */
4230     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4231         IWineD3DDeviceImpl_FindTexUnitMap(This);
4232     }
4233
4234     return WINED3D_OK;
4235 }
4236
4237 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4238     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4239     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4240
4241     /* Reject invalid texture units */
4242     if (Stage >= GL_LIMITS(sampler_stages)) {
4243         TRACE("Attempt to access invalid texture rejected\n");
4244         return WINED3DERR_INVALIDCALL;
4245     }
4246     *ppTexture=This->stateBlock->textures[Stage];
4247     if (*ppTexture)
4248         IWineD3DBaseTexture_AddRef(*ppTexture);
4249
4250     return WINED3D_OK;
4251 }
4252
4253 /*****
4254  * Get Back Buffer
4255  *****/
4256 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4257                                                 IWineD3DSurface **ppBackBuffer) {
4258     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4259     IWineD3DSwapChain *swapChain;
4260     HRESULT hr;
4261
4262     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4263
4264     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4265     if (hr == WINED3D_OK) {
4266         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4267             IWineD3DSwapChain_Release(swapChain);
4268     } else {
4269         *ppBackBuffer = NULL;
4270     }
4271     return hr;
4272 }
4273
4274 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4275     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4276     WARN("(%p) : stub, calling idirect3d for now\n", This);
4277     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4278 }
4279
4280 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4281     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4282     IWineD3DSwapChain *swapChain;
4283     HRESULT hr;
4284
4285     if(iSwapChain > 0) {
4286         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4287         if (hr == WINED3D_OK) {
4288             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4289             IWineD3DSwapChain_Release(swapChain);
4290         } else {
4291             FIXME("(%p) Error getting display mode\n", This);
4292         }
4293     } else {
4294         /* Don't read the real display mode,
4295            but return the stored mode instead. X11 can't change the color
4296            depth, and some apps are pretty angry if they SetDisplayMode from
4297            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4298
4299            Also don't relay to the swapchain because with ddraw it's possible
4300            that there isn't a swapchain at all */
4301         pMode->Width = This->ddraw_width;
4302         pMode->Height = This->ddraw_height;
4303         pMode->Format = This->ddraw_format;
4304         pMode->RefreshRate = 0;
4305         hr = WINED3D_OK;
4306     }
4307
4308     return hr;
4309 }
4310
4311 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4312     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4313     TRACE("(%p)->(%p)\n", This, hWnd);
4314
4315     This->ddraw_window = hWnd;
4316     return WINED3D_OK;
4317 }
4318
4319 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4320     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4321     TRACE("(%p)->(%p)\n", This, hWnd);
4322
4323     *hWnd = This->ddraw_window;
4324     return WINED3D_OK;
4325 }
4326
4327 /*****
4328  * Stateblock related functions
4329  *****/
4330
4331 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4332     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4333     IWineD3DStateBlockImpl *object;
4334     HRESULT temp_result;
4335     
4336     TRACE("(%p)\n", This);
4337     
4338     if (This->isRecordingState) {
4339         return WINED3DERR_INVALIDCALL;
4340     }
4341     
4342     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4343     if (NULL == object ) {
4344         FIXME("(%p)Error allocating memory for stateblock\n", This);
4345         return E_OUTOFMEMORY;
4346     }
4347     TRACE("(%p) created object %p\n", This, object);
4348     object->wineD3DDevice= This;
4349     /** FIXME: object->parent       = parent; **/
4350     object->parent       = NULL;
4351     object->blockType    = WINED3DSBT_ALL;
4352     object->ref          = 1;
4353     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4354     
4355     temp_result = allocate_shader_constants(object);
4356     if (WINED3D_OK != temp_result)
4357         return temp_result;
4358
4359     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4360     This->updateStateBlock = object;
4361     This->isRecordingState = TRUE;
4362
4363     TRACE("(%p) recording stateblock %p\n",This , object);
4364     return WINED3D_OK;
4365 }
4366
4367 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4368     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4369
4370     if (!This->isRecordingState) {
4371         FIXME("(%p) not recording! returning error\n", This);
4372         *ppStateBlock = NULL;
4373         return WINED3DERR_INVALIDCALL;
4374     }
4375
4376     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4377     This->isRecordingState = FALSE;
4378     This->updateStateBlock = This->stateBlock;
4379     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4380     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4381     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4382     return WINED3D_OK;
4383 }
4384
4385 /*****
4386  * Scene related functions
4387  *****/
4388 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4389     /* At the moment we have no need for any functionality at the beginning
4390        of a scene                                                          */
4391     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4392     TRACE("(%p)\n", This);
4393
4394     if(This->inScene) {
4395         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4396         return WINED3DERR_INVALIDCALL;
4397     }
4398     This->inScene = TRUE;
4399     return WINED3D_OK;
4400 }
4401
4402 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4403     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4404     TRACE("(%p)\n", This);
4405
4406     if(!This->inScene) {
4407         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4408         return WINED3DERR_INVALIDCALL;
4409     }
4410
4411     ENTER_GL();
4412     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4413     glFlush();
4414     checkGLcall("glFlush");
4415     LEAVE_GL();
4416
4417     This->inScene = FALSE;
4418     return WINED3D_OK;
4419 }
4420
4421 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4422                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4423                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4424     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4425     IWineD3DSwapChain *swapChain = NULL;
4426     int i;
4427     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4428
4429     TRACE("(%p) Presenting the frame\n", This);
4430
4431     for(i = 0 ; i < swapchains ; i ++) {
4432
4433         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4434         TRACE("presentinng chain %d, %p\n", i, swapChain);
4435         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4436         IWineD3DSwapChain_Release(swapChain);
4437     }
4438
4439     return WINED3D_OK;
4440 }
4441
4442 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4443                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4444     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4445
4446     /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
4447       render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
4448       when the depth-buffer format does not contain stencil buffer information, this method fails. */
4449     GLbitfield     glMask = 0;
4450     GLboolean      old_ztest;
4451     GLfloat        old_z_clear_value;
4452     GLint          old_stencil_clear_value;
4453     GLfloat        old_color_clear_value[4];
4454     unsigned int   i;
4455     CONST WINED3DRECT* curRect;
4456
4457     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
4458           Count, pRects, Flags, Z, Stencil);
4459
4460     ENTER_GL();
4461
4462     glEnable(GL_SCISSOR_TEST);
4463     checkGLcall("glEnable GL_SCISSOR_TEST");
4464
4465     if (Count > 0 && pRects) {
4466         curRect = pRects;
4467     } else {
4468         curRect = NULL;
4469     }
4470
4471     /* Only set the values up once, as they are not changing */
4472     if (Flags & WINED3DCLEAR_STENCIL) {
4473         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4474         glClearStencil(Stencil);
4475         checkGLcall("glClearStencil");
4476         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4477         glStencilMask(0xFFFFFFFF);
4478     }
4479
4480     if (Flags & WINED3DCLEAR_ZBUFFER) {
4481         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4482         glDepthMask(GL_TRUE);
4483         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4484         glClearDepth(Z);
4485         checkGLcall("glClearDepth");
4486         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4487     }
4488
4489     if (Flags & WINED3DCLEAR_TARGET) {
4490         TRACE("Clearing screen with glClear to color %x\n", Color);
4491         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4492         glClearColor(D3DCOLOR_R(Color),
4493                      D3DCOLOR_G(Color),
4494                      D3DCOLOR_B(Color),
4495                      D3DCOLOR_A(Color));
4496         checkGLcall("glClearColor");
4497
4498         /* Clear ALL colors! */
4499         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4500         glMask = glMask | GL_COLOR_BUFFER_BIT;
4501     }
4502
4503     /* Now process each rect in turn */
4504     for (i = 0; i < Count || i == 0; i++) {
4505
4506         if (curRect) {
4507             /* Note gl uses lower left, width/height */
4508             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4509                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4510                   curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4511                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4512             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4513                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4514             checkGLcall("glScissor");
4515         } else {
4516             glScissor(This->stateBlock->viewport.X,
4517                       (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4518                       (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4519                       This->stateBlock->viewport.Width,
4520                       This->stateBlock->viewport.Height);
4521             checkGLcall("glScissor");
4522         }
4523
4524         /* Clear the selected rectangle (or full screen) */
4525         glClear(glMask);
4526         checkGLcall("glClear");
4527
4528         /* Step to the next rectangle */
4529         if (curRect) curRect = curRect + sizeof(WINED3DRECT);
4530     }
4531
4532     /* Restore the old values (why..?) */
4533     if (Flags & WINED3DCLEAR_STENCIL) {
4534         glClearStencil(old_stencil_clear_value);
4535         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4536     }
4537     if (Flags & WINED3DCLEAR_ZBUFFER) {
4538         glDepthMask(old_ztest);
4539         glClearDepth(old_z_clear_value);
4540     }
4541     if (Flags & WINED3DCLEAR_TARGET) {
4542         glClearColor(old_color_clear_value[0],
4543                      old_color_clear_value[1],
4544                      old_color_clear_value[2],
4545                      old_color_clear_value[3]);
4546         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4547                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4548                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4549                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4550     }
4551
4552     glDisable(GL_SCISSOR_TEST);
4553     checkGLcall("glDisable");
4554     LEAVE_GL();
4555
4556     return WINED3D_OK;
4557 }
4558
4559 /*****
4560  * Drawing functions
4561  *****/
4562 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4563                                                 UINT PrimitiveCount) {
4564
4565     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4566     This->stateBlock->streamIsUP = FALSE;
4567
4568     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4569                                debug_d3dprimitivetype(PrimitiveType),
4570                                StartVertex, PrimitiveCount);
4571
4572     if(This->stateBlock->loadBaseVertexIndex != 0) {
4573         This->stateBlock->loadBaseVertexIndex = 0;
4574         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4575     }
4576     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4577     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4578                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4579     return WINED3D_OK;
4580 }
4581
4582 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4583 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4584                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4585                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4586
4587     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4588     UINT                 idxStride = 2;
4589     IWineD3DIndexBuffer *pIB;
4590     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4591
4592     pIB = This->stateBlock->pIndexData;
4593     This->stateBlock->streamIsUP = FALSE;
4594
4595     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4596           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4597           minIndex, NumVertices, startIndex, primCount);
4598
4599     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4600     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4601         idxStride = 2;
4602     } else {
4603         idxStride = 4;
4604     }
4605
4606     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4607         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4608         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4609     }
4610
4611     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4612                    idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4613
4614     return WINED3D_OK;
4615 }
4616
4617 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4618                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4619                                                     UINT VertexStreamZeroStride) {
4620     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4621
4622     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4623              debug_d3dprimitivetype(PrimitiveType),
4624              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4625
4626     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4627     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4628     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4629     This->stateBlock->streamIsUP = TRUE;
4630     This->stateBlock->loadBaseVertexIndex = 0;
4631
4632     /* TODO: Only mark dirty if drawing from a different UP address */
4633     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4634
4635     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4636                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4637
4638     /* MSDN specifies stream zero settings must be set to NULL */
4639     This->stateBlock->streamStride[0] = 0;
4640     This->stateBlock->streamSource[0] = NULL;
4641
4642     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4643      * the new stream sources or use UP drawing again
4644      */
4645     return WINED3D_OK;
4646 }
4647
4648 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4649                                                              UINT MinVertexIndex, UINT NumVertices,
4650                                                              UINT PrimitiveCount, CONST void* pIndexData,
4651                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4652                                                              UINT VertexStreamZeroStride) {
4653     int                 idxStride;
4654     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4655
4656     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4657              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4658              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4659              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4660
4661     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4662         idxStride = 2;
4663     } else {
4664         idxStride = 4;
4665     }
4666
4667     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4668     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4669     This->stateBlock->streamIsUP = TRUE;
4670     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4671
4672     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4673     This->stateBlock->baseVertexIndex = 0;
4674     This->stateBlock->loadBaseVertexIndex = 0;
4675     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4676     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4677
4678     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4679
4680     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4681     This->stateBlock->streamSource[0] = NULL;
4682     This->stateBlock->streamStride[0] = 0;
4683     This->stateBlock->pIndexData = NULL;
4684     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4685      * SetStreamSource to specify a vertex buffer
4686      */
4687
4688     return WINED3D_OK;
4689 }
4690
4691 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4692     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4693
4694     /* Mark the state dirty until we have nicer tracking
4695      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4696      * that value.
4697      */
4698     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4699     This->stateBlock->baseVertexIndex = 0;
4700     This->up_strided = DrawPrimStrideData;
4701     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4702     This->up_strided = NULL;
4703     return WINED3D_OK;
4704 }
4705  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4706 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4707     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4708     HRESULT hr = WINED3D_OK;
4709     WINED3DRESOURCETYPE sourceType;
4710     WINED3DRESOURCETYPE destinationType;
4711     int i ,levels;
4712
4713     /* TODO: think about moving the code into IWineD3DBaseTexture  */
4714
4715     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4716
4717     /* verify that the source and destination textures aren't NULL */
4718     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4719         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4720              This, pSourceTexture, pDestinationTexture);
4721         hr = WINED3DERR_INVALIDCALL;
4722     }
4723
4724     if (pSourceTexture == pDestinationTexture) {
4725         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4726              This, pSourceTexture, pDestinationTexture);
4727         hr = WINED3DERR_INVALIDCALL;
4728     }
4729     /* Verify that the source and destination textures are the same type */
4730     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
4731     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4732
4733     if (sourceType != destinationType) {
4734         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4735              This);
4736         hr = WINED3DERR_INVALIDCALL;
4737     }
4738
4739     /* check that both textures have the identical numbers of levels  */
4740     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4741         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4742         hr = WINED3DERR_INVALIDCALL;
4743     }
4744
4745     if (WINED3D_OK == hr) {
4746
4747         /* Make sure that the destination texture is loaded */
4748         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4749
4750         /* Update every surface level of the texture */
4751         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4752
4753         switch (sourceType) {
4754         case WINED3DRTYPE_TEXTURE:
4755             {
4756                 IWineD3DSurface *srcSurface;
4757                 IWineD3DSurface *destSurface;
4758
4759                 for (i = 0 ; i < levels ; ++i) {
4760                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
4761                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4762                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4763                     IWineD3DSurface_Release(srcSurface);
4764                     IWineD3DSurface_Release(destSurface);
4765                     if (WINED3D_OK != hr) {
4766                         WARN("(%p) : Call to update surface failed\n", This);
4767                         return hr;
4768                     }
4769                 }
4770             }
4771             break;
4772         case WINED3DRTYPE_CUBETEXTURE:
4773             {
4774                 IWineD3DSurface *srcSurface;
4775                 IWineD3DSurface *destSurface;
4776                 WINED3DCUBEMAP_FACES faceType;
4777
4778                 for (i = 0 ; i < levels ; ++i) {
4779                     /* Update each cube face */
4780                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4781                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
4782                         if (WINED3D_OK != hr) {
4783                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4784                         } else {
4785                             TRACE("Got srcSurface %p\n", srcSurface);
4786                         }
4787                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4788                         if (WINED3D_OK != hr) {
4789                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4790                         } else {
4791                             TRACE("Got desrSurface %p\n", destSurface);
4792                         }
4793                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4794                         IWineD3DSurface_Release(srcSurface);
4795                         IWineD3DSurface_Release(destSurface);
4796                         if (WINED3D_OK != hr) {
4797                             WARN("(%p) : Call to update surface failed\n", This);
4798                             return hr;
4799                         }
4800                     }
4801                 }
4802             }
4803             break;
4804 #if 0 /* TODO: Add support for volume textures */
4805         case WINED3DRTYPE_VOLUMETEXTURE:
4806             {
4807                 IWineD3DVolume  srcVolume  = NULL;
4808                 IWineD3DSurface destVolume = NULL;
4809
4810                 for (i = 0 ; i < levels ; ++i) {
4811                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
4812                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4813                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4814                     IWineD3DVolume_Release(srcSurface);
4815                     IWineD3DVolume_Release(destSurface);
4816                     if (WINED3D_OK != hr) {
4817                         WARN("(%p) : Call to update volume failed\n", This);
4818                         return hr;
4819                     }
4820                 }
4821             }
4822             break;
4823 #endif
4824         default:
4825             FIXME("(%p) : Unsupported source and destination type\n", This);
4826             hr = WINED3DERR_INVALIDCALL;
4827         }
4828     }
4829
4830     return hr;
4831 }
4832
4833 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4834     IWineD3DSwapChain *swapChain;
4835     HRESULT hr;
4836     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4837     if(hr == WINED3D_OK) {
4838         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4839                 IWineD3DSwapChain_Release(swapChain);
4840     }
4841     return hr;
4842 }
4843
4844 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4845     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4846     /* return a sensible default */
4847     *pNumPasses = 1;
4848     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
4849     FIXME("(%p) : stub\n", This);
4850     return WINED3D_OK;
4851 }
4852
4853 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4854     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4855     int j;
4856     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4857     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4858         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4859         return WINED3DERR_INVALIDCALL;
4860     }
4861     for (j = 0; j < 256; ++j) {
4862         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
4863         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4864         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
4865         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4866     }
4867     TRACE("(%p) : returning\n", This);
4868     return WINED3D_OK;
4869 }
4870
4871 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4872     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4873     int j;
4874     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4875     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4876         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4877         return WINED3DERR_INVALIDCALL;
4878     }
4879     for (j = 0; j < 256; ++j) {
4880         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
4881         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4882         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
4883         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4884     }
4885     TRACE("(%p) : returning\n", This);
4886     return WINED3D_OK;
4887 }
4888
4889 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4890     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4891     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4892     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4893         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4894         return WINED3DERR_INVALIDCALL;
4895     }
4896     /*TODO: stateblocks */
4897     This->currentPalette = PaletteNumber;
4898     TRACE("(%p) : returning\n", This);
4899     return WINED3D_OK;
4900 }
4901
4902 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4903     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4904     if (PaletteNumber == NULL) {
4905         WARN("(%p) : returning Invalid Call\n", This);
4906         return WINED3DERR_INVALIDCALL;
4907     }
4908     /*TODO: stateblocks */
4909     *PaletteNumber = This->currentPalette;
4910     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
4911     return WINED3D_OK;
4912 }
4913
4914 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4915     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4916     static BOOL showFixmes = TRUE;
4917     if (showFixmes) {
4918         FIXME("(%p) : stub\n", This);
4919         showFixmes = FALSE;
4920     }
4921
4922     This->softwareVertexProcessing = bSoftware;
4923     return WINED3D_OK;
4924 }
4925
4926
4927 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4928     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4929     static BOOL showFixmes = TRUE;
4930     if (showFixmes) {
4931         FIXME("(%p) : stub\n", This);
4932         showFixmes = FALSE;
4933     }
4934     return This->softwareVertexProcessing;
4935 }
4936
4937
4938 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
4939     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4940     IWineD3DSwapChain *swapChain;
4941     HRESULT hr;
4942
4943     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4944
4945     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4946     if(hr == WINED3D_OK){
4947         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4948         IWineD3DSwapChain_Release(swapChain);
4949     }else{
4950         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
4951     }
4952     return hr;
4953 }
4954
4955
4956 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4957     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4958     static BOOL showfixmes = TRUE;
4959     if(nSegments != 0.0f) {
4960         if( showfixmes) {
4961             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4962             showfixmes = FALSE;
4963         }
4964     }
4965     return WINED3D_OK;
4966 }
4967
4968 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4969     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4970     static BOOL showfixmes = TRUE;
4971     if( showfixmes) {
4972         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4973         showfixmes = FALSE;
4974     }
4975     return 0.0f;
4976 }
4977
4978 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4979     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
4980     /** TODO: remove casts to IWineD3DSurfaceImpl
4981      *       NOTE: move code to surface to accomplish this
4982       ****************************************/
4983     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
4984     int srcWidth, srcHeight;
4985     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4986     WINED3DFORMAT destFormat, srcFormat;
4987     UINT          destSize;
4988     int srcLeft, destLeft, destTop;
4989     WINED3DPOOL       srcPool, destPool;
4990     int offset    = 0;
4991     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4992     glDescriptor *glDescription = NULL;
4993     GLenum textureDimensions = GL_TEXTURE_2D;
4994     IWineD3DBaseTexture *baseTexture;
4995
4996     WINED3DSURFACE_DESC  winedesc;
4997
4998     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
4999     memset(&winedesc, 0, sizeof(winedesc));
5000     winedesc.Width  = &srcSurfaceWidth;
5001     winedesc.Height = &srcSurfaceHeight;
5002     winedesc.Pool   = &srcPool;
5003     winedesc.Format = &srcFormat;
5004
5005     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5006
5007     winedesc.Width  = &destSurfaceWidth;
5008     winedesc.Height = &destSurfaceHeight;
5009     winedesc.Pool   = &destPool;
5010     winedesc.Format = &destFormat;
5011     winedesc.Size   = &destSize;
5012
5013     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5014
5015     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5016         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5017         return WINED3DERR_INVALIDCALL;
5018     }
5019
5020     if (destFormat == WINED3DFMT_UNKNOWN) {
5021         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5022         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5023
5024         /* Get the update surface description */
5025         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5026     }
5027
5028     /* Make sure the surface is loaded and up to date */
5029     IWineD3DSurface_PreLoad(pDestinationSurface);
5030
5031     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5032
5033     ENTER_GL();
5034
5035     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5036     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5037     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
5038     srcLeft    = pSourceRect ? pSourceRect->left : 0;
5039     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5040     destTop    = pDestPoint  ? pDestPoint->y : 0;
5041
5042
5043     /* This function doesn't support compressed textures
5044     the pitch is just bytesPerPixel * width */
5045     if(srcWidth != srcSurfaceWidth  || srcLeft ){
5046         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5047         offset   += srcLeft * pSrcSurface->bytesPerPixel;
5048         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5049     }
5050     /* TODO DXT formats */
5051
5052     if(pSourceRect != NULL && pSourceRect->top != 0){
5053        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5054     }
5055     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5056     ,This
5057     ,glDescription->level
5058     ,destLeft
5059     ,destTop
5060     ,srcWidth
5061     ,srcHeight
5062     ,glDescription->glFormat
5063     ,glDescription->glType
5064     ,IWineD3DSurface_GetData(pSourceSurface)
5065     );
5066
5067     /* Sanity check */
5068     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5069
5070         /* need to lock the surface to get the data */
5071         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5072     }
5073
5074     /* TODO: Cube and volume support */
5075     if(rowoffset != 0){
5076         /* not a whole row so we have to do it a line at a time */
5077         int j;
5078
5079         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5080         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5081
5082         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5083
5084                 glTexSubImage2D(glDescription->target
5085                     ,glDescription->level
5086                     ,destLeft
5087                     ,j
5088                     ,srcWidth
5089                     ,1
5090                     ,glDescription->glFormat
5091                     ,glDescription->glType
5092                     ,data /* could be quicker using */
5093                 );
5094             data += rowoffset;
5095         }
5096
5097     } else { /* Full width, so just write out the whole texture */
5098
5099         if (WINED3DFMT_DXT1 == destFormat ||
5100             WINED3DFMT_DXT2 == destFormat ||
5101             WINED3DFMT_DXT3 == destFormat ||
5102             WINED3DFMT_DXT4 == destFormat ||
5103             WINED3DFMT_DXT5 == destFormat) {
5104             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5105                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5106                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5107                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5108                 } if (destFormat != srcFormat) {
5109                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5110                 } else {
5111                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5112                                                         glDescription->level,
5113                                                         glDescription->glFormatInternal,
5114                                                         srcWidth,
5115                                                         srcHeight,
5116                                                         0,
5117                                                         destSize,
5118                                                         IWineD3DSurface_GetData(pSourceSurface));
5119                 }
5120             } else {
5121                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5122             }
5123
5124
5125         } else {
5126             if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5127
5128                 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5129                 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5130                 data returned by GetData non-power2 width/height with hardware non-power2
5131                 pow2Width/height are set to surface width height, repacking isn't needed so it
5132                 doesn't matter which function gets called. */
5133                 glTexSubImage2D(glDescription->target
5134                         ,glDescription->level
5135                         ,destLeft
5136                         ,destTop
5137                         ,srcWidth
5138                         ,srcHeight
5139                         ,glDescription->glFormat
5140                         ,glDescription->glType
5141                         ,IWineD3DSurface_GetData(pSourceSurface)
5142                     );
5143             } else {
5144
5145                 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5146                 glTexSubImage2D(glDescription->target
5147                     ,glDescription->level
5148                     ,destLeft
5149                     ,destTop
5150                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5151                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5152                     ,glDescription->glFormat
5153                     ,glDescription->glType
5154                     ,IWineD3DSurface_GetData(pSourceSurface)
5155                 );
5156             }
5157
5158         }
5159      }
5160     checkGLcall("glTexSubImage2D");
5161     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
5162
5163     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5164      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5165      * surface bigger than it needs to be hmm.. */
5166     if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5167         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5168         IWineD3DBaseTexture_Release(baseTexture);
5169     }
5170
5171     glDisable(textureDimensions); /* This needs to be managed better.... */
5172     LEAVE_GL();
5173
5174     return WINED3D_OK;
5175 }
5176
5177 /* Implementation details at http://developer.nvidia.com/attach/6494
5178 and
5179 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5180 hmm.. no longer supported use
5181 OpenGL evaluators or  tessellate surfaces within your application.
5182 */
5183
5184 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5185 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5186     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5187     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5188     FIXME("(%p) : Stub\n", This);
5189     return WINED3D_OK;
5190
5191 }
5192
5193 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5194 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5195     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5196     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5197     FIXME("(%p) : Stub\n", This);
5198     return WINED3D_OK;
5199 }
5200
5201 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5202     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5203     TRACE("(%p) Handle(%d)\n", This, Handle);
5204     FIXME("(%p) : Stub\n", This);
5205     return WINED3D_OK;
5206 }
5207
5208 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
5209     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5210     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
5211     DDBLTFX BltFx;
5212     TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
5213
5214     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
5215         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5216         return WINED3DERR_INVALIDCALL;
5217     }
5218
5219     /* Just forward this to the DirectDraw blitting engine */
5220     memset(&BltFx, 0, sizeof(BltFx));
5221     BltFx.dwSize = sizeof(BltFx);
5222     BltFx.u5.dwFillColor = color;
5223     return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
5224 }
5225
5226 /* rendertarget and deptth stencil functions */
5227 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5228     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5229
5230     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5231         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5232         return WINED3DERR_INVALIDCALL;
5233     }
5234
5235     *ppRenderTarget = This->render_targets[RenderTargetIndex];
5236     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5237     /* Note inc ref on returned surface */
5238     if(*ppRenderTarget != NULL)
5239         IWineD3DSurface_AddRef(*ppRenderTarget);
5240     return WINED3D_OK;
5241 }
5242
5243 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
5244     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5245     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
5246     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
5247     IWineD3DSwapChainImpl *Swapchain;
5248     HRESULT hr;
5249
5250     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
5251
5252     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
5253     if(hr != WINED3D_OK) {
5254         ERR("Can't get the swapchain\n");
5255         return hr;
5256     }
5257
5258     /* Make sure to release the swapchain */
5259     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
5260
5261     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
5262         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5263         return WINED3DERR_INVALIDCALL;
5264     }
5265     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
5266         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5267         return WINED3DERR_INVALIDCALL;
5268     }
5269
5270     if(Swapchain->frontBuffer != Front) {
5271         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
5272
5273         if(Swapchain->frontBuffer)
5274             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
5275         Swapchain->frontBuffer = Front;
5276
5277         if(Swapchain->frontBuffer) {
5278             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
5279         }
5280     }
5281
5282     if(Back && !Swapchain->backBuffer) {
5283         /* We need memory for the back buffer array - only one back buffer this way */
5284         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
5285         if(!Swapchain->backBuffer) {
5286             ERR("Out of memory\n");
5287             return E_OUTOFMEMORY;
5288         }
5289     }
5290
5291     if(Swapchain->backBuffer[0] != Back) {
5292         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
5293         ENTER_GL();
5294         if(!Swapchain->backBuffer[0]) {
5295             /* GL was told to draw to the front buffer at creation,
5296              * undo that
5297              */
5298             glDrawBuffer(GL_BACK);
5299             checkGLcall("glDrawBuffer(GL_BACK)");
5300             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
5301             Swapchain->presentParms.BackBufferCount = 1;
5302         } else if (!Back) {
5303             /* That makes problems - disable for now */
5304             /* glDrawBuffer(GL_FRONT); */
5305             checkGLcall("glDrawBuffer(GL_FRONT)");
5306             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
5307             Swapchain->presentParms.BackBufferCount = 0;
5308         }
5309         LEAVE_GL();
5310
5311         if(Swapchain->backBuffer[0])
5312             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
5313         Swapchain->backBuffer[0] = Back;
5314
5315         if(Swapchain->backBuffer[0]) {
5316             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5317         } else {
5318             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5319         }
5320
5321     }
5322
5323     return WINED3D_OK;
5324 }
5325
5326 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5327     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5328     *ppZStencilSurface = This->depthStencilBuffer;
5329     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5330
5331     if(*ppZStencilSurface != NULL) {
5332         /* Note inc ref on returned surface */
5333         IWineD3DSurface_AddRef(*ppZStencilSurface);
5334     }
5335     return WINED3D_OK;
5336 }
5337
5338 static void bind_fbo(IWineD3DDevice *iface) {
5339     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5340
5341     if (!This->fbo) {
5342         GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
5343         checkGLcall("glGenFramebuffersEXT()");
5344     }
5345     GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
5346     checkGLcall("glBindFramebuffer()");
5347 }
5348
5349 /* TODO: Handle stencil attachments */
5350 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5351     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5352     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5353
5354     This->depth_copy_state = WINED3D_DCS_NO_COPY;
5355
5356     bind_fbo(iface);
5357
5358     if (depth_stencil_impl) {
5359         GLenum texttarget, target;
5360         GLint old_binding = 0;
5361
5362         IWineD3DSurface_PreLoad(depth_stencil);
5363         texttarget = depth_stencil_impl->glDescription.target;
5364         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5365
5366         glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5367         glBindTexture(target, depth_stencil_impl->glDescription.textureName);
5368         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5369         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5370         glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5371         glBindTexture(target, old_binding);
5372
5373         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5374         checkGLcall("glFramebufferTexture2DEXT()");
5375     } else {
5376         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5377         checkGLcall("glFramebufferTexture2DEXT()");
5378     }
5379
5380     if (!This->render_offscreen) {
5381         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5382         checkGLcall("glBindFramebuffer()");
5383     }
5384 }
5385
5386 void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5387     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5388     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5389
5390     if (idx >= GL_LIMITS(buffers)) {
5391         ERR("%p : Trying to set render target %d, but only %d supported\n", This, idx, GL_LIMITS(buffers));
5392     }
5393
5394     bind_fbo(iface);
5395
5396     if (rtimpl) {
5397         GLenum texttarget, target;
5398         GLint old_binding = 0;
5399
5400         IWineD3DSurface_PreLoad(render_target);
5401         texttarget = rtimpl->glDescription.target;
5402         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5403
5404         glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5405         glBindTexture(target, rtimpl->glDescription.textureName);
5406         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5407         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5408         glBindTexture(target, old_binding);
5409
5410         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, rtimpl->glDescription.textureName, 0));
5411         checkGLcall("glFramebufferTexture2DEXT()");
5412
5413         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5414     } else {
5415         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5416         checkGLcall("glFramebufferTexture2DEXT()");
5417
5418         This->draw_buffers[idx] = GL_NONE;
5419     }
5420
5421     if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5422         GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5423         checkGLcall("glDrawBuffers()");
5424     }
5425
5426     if (!This->render_offscreen) {
5427         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5428         checkGLcall("glBindFramebuffer()");
5429     }
5430 }
5431
5432 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5433     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5434     WINED3DVIEWPORT viewport;
5435
5436     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5437
5438     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5439         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5440         return WINED3DERR_INVALIDCALL;
5441     }
5442
5443     /* MSDN says that null disables the render target
5444     but a device must always be associated with a render target
5445     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5446
5447     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5448     for more details
5449     */
5450     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5451         FIXME("Trying to set render target 0 to NULL\n");
5452         return WINED3DERR_INVALIDCALL;
5453     }
5454     if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5455         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);
5456         return WINED3DERR_INVALIDCALL;
5457     }
5458
5459     /* If we are trying to set what we already have, don't bother */
5460     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5461         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5462         return WINED3D_OK;
5463     }
5464     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5465     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5466     This->render_targets[RenderTargetIndex] = pRenderTarget;
5467
5468     /* Render target 0 is special */
5469     if(RenderTargetIndex == 0) {
5470         /* Finally, reset the viewport as the MSDN states. */
5471         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5472         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5473         viewport.X      = 0;
5474         viewport.Y      = 0;
5475         viewport.MaxZ   = 1.0f;
5476         viewport.MinZ   = 0.0f;
5477         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5478
5479         /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
5480          * ctx properly.
5481          * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
5482          * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
5483          */
5484         ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
5485     } else {
5486         /* We only get more than 1 render target with fbos, so no need to check the offscreen rendering method */
5487         set_render_target_fbo(iface, RenderTargetIndex, pRenderTarget);
5488     }
5489     return WINED3D_OK;
5490 }
5491
5492 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5493     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5494     HRESULT  hr = WINED3D_OK;
5495     IWineD3DSurface *tmp;
5496
5497     TRACE("(%p) Swapping z-buffer\n",This);
5498
5499     if (pNewZStencil == This->stencilBufferTarget) {
5500         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5501     } else {
5502         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5503         * depending on the renter target implementation being used.
5504         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5505         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5506         * stencil buffer and incure an extra memory overhead
5507          ******************************************************/
5508
5509
5510         tmp = This->stencilBufferTarget;
5511         This->stencilBufferTarget = pNewZStencil;
5512         /* should we be calling the parent or the wined3d surface? */
5513         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5514         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5515         hr = WINED3D_OK;
5516         /** TODO: glEnable/glDisable on depth/stencil    depending on
5517          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
5518           **********************************************************/
5519         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5520             set_depth_stencil_fbo(iface, pNewZStencil);
5521         }
5522     }
5523
5524     return hr;
5525 }
5526
5527 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5528                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5529     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5530     /* TODO: the use of Impl is deprecated. */
5531     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5532
5533     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5534
5535     /* some basic validation checks */
5536     if(This->cursorTexture) {
5537         ENTER_GL();
5538         glDeleteTextures(1, &This->cursorTexture);
5539         LEAVE_GL();
5540         This->cursorTexture = 0;
5541     }
5542
5543     if(pCursorBitmap) {
5544         /* MSDN: Cursor must be A8R8G8B8 */
5545         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5546             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5547             return WINED3DERR_INVALIDCALL;
5548         }
5549
5550         /* MSDN: Cursor must be smaller than the display mode */
5551         if(pSur->currentDesc.Width > This->ddraw_width ||
5552            pSur->currentDesc.Height > This->ddraw_height) {
5553             ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %dx%d\n", This, pSur, pSur->currentDesc.Width, pSur->currentDesc.Height, This->ddraw_width, This->ddraw_height);
5554             return WINED3DERR_INVALIDCALL;
5555         }
5556
5557         /* TODO: MSDN: Cursor sizes must be a power of 2 */
5558         /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
5559          * Texture and Blitting code to draw the cursor
5560          */
5561         pSur->Flags |= SFLAG_FORCELOAD;
5562         IWineD3DSurface_PreLoad(pCursorBitmap);
5563         pSur->Flags &= ~SFLAG_FORCELOAD;
5564         /* Do not store the surface's pointer because the application may release
5565          * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
5566          * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
5567          */
5568         This->cursorTexture = pSur->glDescription.textureName;
5569         This->cursorWidth = pSur->currentDesc.Width;
5570         This->cursorHeight = pSur->currentDesc.Height;
5571         pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
5572     }
5573
5574     This->xHotSpot = XHotSpot;
5575     This->yHotSpot = YHotSpot;
5576     return WINED3D_OK;
5577 }
5578
5579 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5580     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5581     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5582
5583     This->xScreenSpace = XScreenSpace;
5584     This->yScreenSpace = YScreenSpace;
5585
5586     return;
5587
5588 }
5589
5590 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5591     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5592     BOOL oldVisible = This->bCursorVisible;
5593     TRACE("(%p) : visible(%d)\n", This, bShow);
5594
5595     if(This->cursorTexture)
5596         This->bCursorVisible = bShow;
5597
5598     return oldVisible;
5599 }
5600
5601 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5602     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5603     TRACE("(%p) : state (%u)\n", This, This->state);
5604     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5605     switch (This->state) {
5606     case WINED3D_OK:
5607         return WINED3D_OK;
5608     case WINED3DERR_DEVICELOST:
5609         {
5610             ResourceList *resourceList  = This->resources;
5611             while (NULL != resourceList) {
5612                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5613                 return WINED3DERR_DEVICENOTRESET;
5614                 resourceList = resourceList->next;
5615             }
5616             return WINED3DERR_DEVICELOST;
5617         }
5618     case WINED3DERR_DRIVERINTERNALERROR:
5619         return WINED3DERR_DRIVERINTERNALERROR;
5620     }
5621
5622     /* Unknown state */
5623     return WINED3DERR_DRIVERINTERNALERROR;
5624 }
5625
5626
5627 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5628     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5629     /** FIXME: Resource tracking needs to be done,
5630     * The closes we can do to this is set the priorities of all managed textures low
5631     * and then reset them.
5632      ***********************************************************/
5633     FIXME("(%p) : stub\n", This);
5634     return WINED3D_OK;
5635 }
5636
5637 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5638     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
5639     if(surface->Flags & SFLAG_DIBSECTION) {
5640         /* Release the DC */
5641         SelectObject(surface->hDC, surface->dib.holdbitmap);
5642         DeleteDC(surface->hDC);
5643         /* Release the DIB section */
5644         DeleteObject(surface->dib.DIBsection);
5645         surface->dib.bitmap_data = NULL;
5646         surface->resource.allocatedMemory = NULL;
5647         surface->Flags &= ~SFLAG_DIBSECTION;
5648     }
5649     surface->currentDesc.Width = *pPresentationParameters->BackBufferWidth;
5650     surface->currentDesc.Height = *pPresentationParameters->BackBufferHeight;
5651     if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
5652         surface->pow2Width = *pPresentationParameters->BackBufferWidth;
5653         surface->pow2Height = *pPresentationParameters->BackBufferHeight;
5654     } else {
5655         surface->pow2Width = surface->pow2Height = 1;
5656         while (surface->pow2Width < *pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
5657         while (surface->pow2Height < *pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
5658     }
5659     if(surface->glDescription.textureName) {
5660         ENTER_GL();
5661         glDeleteTextures(1, &surface->glDescription.textureName);
5662         LEAVE_GL();
5663         surface->glDescription.textureName = 0;
5664     }
5665     if(surface->pow2Width != *pPresentationParameters->BackBufferWidth ||
5666        surface->pow2Height != *pPresentationParameters->BackBufferHeight) {
5667         surface->Flags |= SFLAG_NONPOW2;
5668     } else  {
5669         surface->Flags &= ~SFLAG_NONPOW2;
5670     }
5671     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
5672     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
5673 }
5674
5675 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5676     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5677     IWineD3DSwapChainImpl *swapchain;
5678     HRESULT hr;
5679     BOOL DisplayModeChanged = FALSE;
5680     WINED3DDISPLAYMODE mode;
5681     TRACE("(%p)\n", This);
5682
5683     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
5684     if(FAILED(hr)) {
5685         ERR("Failed to get the first implicit swapchain\n");
5686         return hr;
5687     }
5688
5689     /* Is it necessary to recreate the gl context? Actually every setting can be changed
5690      * on an existing gl context, so there's no real need for recreation.
5691      *
5692      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
5693      *
5694      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
5695      */
5696     TRACE("New params:\n");
5697     TRACE("BackBufferWidth = %d\n", *pPresentationParameters->BackBufferWidth);
5698     TRACE("BackBufferHeight = %d\n", *pPresentationParameters->BackBufferHeight);
5699     TRACE("BackBufferFormat = %s\n", debug_d3dformat(*pPresentationParameters->BackBufferFormat));
5700     TRACE("BackBufferCount = %d\n", *pPresentationParameters->BackBufferCount);
5701     TRACE("MultiSampleType = %d\n", *pPresentationParameters->MultiSampleType);
5702     TRACE("MultiSampleQuality = %d\n", *pPresentationParameters->MultiSampleQuality);
5703     TRACE("SwapEffect = %d\n", *pPresentationParameters->SwapEffect);
5704     TRACE("hDeviceWindow = %p\n", *pPresentationParameters->hDeviceWindow);
5705     TRACE("Windowed = %s\n", *pPresentationParameters->Windowed ? "true" : "false");
5706     TRACE("EnableAutoDepthStencil = %s\n", *pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
5707     TRACE("Flags = %08x\n", *pPresentationParameters->Flags);
5708     TRACE("FullScreen_RefreshRateInHz = %d\n", *pPresentationParameters->FullScreen_RefreshRateInHz);
5709     TRACE("PresentationInterval = %d\n", *pPresentationParameters->PresentationInterval);
5710
5711     /* No special treatment of these parameters. Just store them */
5712     swapchain->presentParms.SwapEffect = *pPresentationParameters->SwapEffect;
5713     swapchain->presentParms.Flags = *pPresentationParameters->Flags;
5714     swapchain->presentParms.PresentationInterval = *pPresentationParameters->PresentationInterval;
5715     swapchain->presentParms.FullScreen_RefreshRateInHz = *pPresentationParameters->FullScreen_RefreshRateInHz;
5716
5717     /* What to do about these? */
5718     if(*pPresentationParameters->BackBufferCount != 0 &&
5719         *pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
5720         ERR("Cannot change the back buffer count yet\n");
5721     }
5722     if(*pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
5723         *pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
5724         ERR("Cannot change the back buffer format yet\n");
5725     }
5726     if(*pPresentationParameters->hDeviceWindow != NULL &&
5727         *pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
5728         ERR("Cannot change the device window yet\n");
5729     }
5730     if(*pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
5731         ERR("What do do about a changed auto depth stencil parameter?\n");
5732     }
5733
5734     if(*pPresentationParameters->Windowed) {
5735         mode.Width = swapchain->orig_width;
5736         mode.Height = swapchain->orig_height;
5737         mode.RefreshRate = 0;
5738         mode.Format = swapchain->presentParms.BackBufferFormat;
5739     } else {
5740         mode.Width = *pPresentationParameters->BackBufferWidth;
5741         mode.Height = *pPresentationParameters->BackBufferHeight;
5742         mode.RefreshRate = *pPresentationParameters->FullScreen_RefreshRateInHz;
5743         mode.Format = swapchain->presentParms.BackBufferFormat;
5744     }
5745
5746     /* Should Width == 800 && Height == 0 set 800x600? */
5747     if(*pPresentationParameters->BackBufferWidth != 0 && *pPresentationParameters->BackBufferHeight != 0 &&
5748        (*pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
5749         *pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
5750     {
5751         WINED3DVIEWPORT vp;
5752         int i;
5753
5754         vp.X = 0;
5755         vp.Y = 0;
5756         vp.Width = *pPresentationParameters->BackBufferWidth;
5757         vp.Height = *pPresentationParameters->BackBufferHeight;
5758         vp.MinZ = 0;
5759         vp.MaxZ = 1;
5760
5761         if(!*pPresentationParameters->Windowed) {
5762             DisplayModeChanged = TRUE;
5763         }
5764         swapchain->presentParms.BackBufferWidth = *pPresentationParameters->BackBufferWidth;
5765         swapchain->presentParms.BackBufferHeight = *pPresentationParameters->BackBufferHeight;
5766
5767         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
5768         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
5769             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
5770         }
5771
5772         /* Now set the new viewport */
5773         IWineD3DDevice_SetViewport(iface, &vp);
5774     }
5775
5776     if((*pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
5777        (swapchain->presentParms.Windowed && !*pPresentationParameters->Windowed) ||
5778         DisplayModeChanged) {
5779         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
5780     }
5781
5782     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
5783     return WINED3D_OK;
5784 }
5785
5786 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5787     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5788     /** FIXME: always true at the moment **/
5789     if(!bEnableDialogs) {
5790         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5791     }
5792     return WINED3D_OK;
5793 }
5794
5795
5796 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
5797     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5798     TRACE("(%p) : pParameters %p\n", This, pParameters);
5799
5800     *pParameters = This->createParms;
5801     return WINED3D_OK;
5802 }
5803
5804 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
5805     IWineD3DSwapChain *swapchain;
5806     HRESULT hrc = WINED3D_OK;
5807
5808     TRACE("Relaying  to swapchain\n");
5809
5810     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5811         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
5812         IWineD3DSwapChain_Release(swapchain);
5813     }
5814     return;
5815 }
5816
5817 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
5818     IWineD3DSwapChain *swapchain;
5819     HRESULT hrc = WINED3D_OK;
5820
5821     TRACE("Relaying  to swapchain\n");
5822
5823     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5824         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5825         IWineD3DSwapChain_Release(swapchain);
5826     }
5827     return;
5828 }
5829
5830
5831 /** ********************************************************
5832 *   Notification functions
5833 ** ********************************************************/
5834 /** This function must be called in the release of a resource when ref == 0,
5835 * the contents of resource must still be correct,
5836 * any handels to other resource held by the caller must be closed
5837 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5838  *****************************************************/
5839 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5840     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5841     ResourceList* resourceList;
5842
5843     TRACE("(%p) : resource %p\n", This, resource);
5844 #if 0
5845     EnterCriticalSection(&resourceStoreCriticalSection);
5846 #endif
5847     /* add a new texture to the frot of the linked list */
5848     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5849     resourceList->resource = resource;
5850
5851     /* Get the old head */
5852     resourceList->next = This->resources;
5853
5854     This->resources = resourceList;
5855     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5856
5857 #if 0
5858     LeaveCriticalSection(&resourceStoreCriticalSection);
5859 #endif
5860     return;
5861 }
5862
5863 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5864     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5865     ResourceList* resourceList = NULL;
5866     ResourceList* previousResourceList = NULL;
5867     
5868     TRACE("(%p) : resource %p\n", This, resource);
5869
5870 #if 0
5871     EnterCriticalSection(&resourceStoreCriticalSection);
5872 #endif
5873     resourceList = This->resources;
5874
5875     while (resourceList != NULL) {
5876         if(resourceList->resource == resource) break;
5877         previousResourceList = resourceList;
5878         resourceList = resourceList->next;
5879     }
5880
5881     if (resourceList == NULL) {
5882         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5883 #if 0
5884         LeaveCriticalSection(&resourceStoreCriticalSection);
5885 #endif
5886         return;
5887     } else {
5888             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5889     }
5890     /* make sure we don't leave a hole in the list */
5891     if (previousResourceList != NULL) {
5892         previousResourceList->next = resourceList->next;
5893     } else {
5894         This->resources = resourceList->next;
5895     }
5896
5897 #if 0
5898     LeaveCriticalSection(&resourceStoreCriticalSection);
5899 #endif
5900     return;
5901 }
5902
5903
5904 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5905     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5906     int counter;
5907
5908     TRACE("(%p) : resource %p\n", This, resource);
5909     switch(IWineD3DResource_GetType(resource)){
5910         case WINED3DRTYPE_SURFACE:
5911         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
5912         break;
5913         case WINED3DRTYPE_TEXTURE:
5914         case WINED3DRTYPE_CUBETEXTURE:
5915         case WINED3DRTYPE_VOLUMETEXTURE:
5916                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
5917                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5918                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5919                         This->stateBlock->textures[counter] = NULL;
5920                     }
5921                     if (This->updateStateBlock != This->stateBlock ){
5922                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5923                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5924                             This->updateStateBlock->textures[counter] = NULL;
5925                         }
5926                     }
5927                 }
5928         break;
5929         case WINED3DRTYPE_VOLUME:
5930         /* TODO: nothing really? */
5931         break;
5932         case WINED3DRTYPE_VERTEXBUFFER:
5933         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5934         {
5935             int streamNumber;
5936             TRACE("Cleaning up stream pointers\n");
5937
5938             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5939                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5940                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5941                 */
5942                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5943                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5944                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5945                         This->updateStateBlock->streamSource[streamNumber] = 0;
5946                         /* Set changed flag? */
5947                     }
5948                 }
5949                 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) */
5950                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5951                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5952                         This->stateBlock->streamSource[streamNumber] = 0;
5953                     }
5954                 }
5955 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5956                  else { /* This shouldn't happen */
5957                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5958                 }
5959 #endif
5960
5961             }
5962         }
5963         break;
5964         case WINED3DRTYPE_INDEXBUFFER:
5965         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5966         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5967             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5968                 This->updateStateBlock->pIndexData =  NULL;
5969             }
5970         }
5971         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5972             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5973                 This->stateBlock->pIndexData =  NULL;
5974             }
5975         }
5976
5977         break;
5978         default:
5979         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
5980         break;
5981     }
5982
5983
5984     /* Remove the resoruce from the resourceStore */
5985     IWineD3DDeviceImpl_RemoveResource(iface, resource);
5986
5987     TRACE("Resource released\n");
5988
5989 }
5990
5991 /**********************************************************
5992  * IWineD3DDevice VTbl follows
5993  **********************************************************/
5994
5995 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5996 {
5997     /*** IUnknown methods ***/
5998     IWineD3DDeviceImpl_QueryInterface,
5999     IWineD3DDeviceImpl_AddRef,
6000     IWineD3DDeviceImpl_Release,
6001     /*** IWineD3DDevice methods ***/
6002     IWineD3DDeviceImpl_GetParent,
6003     /*** Creation methods**/
6004     IWineD3DDeviceImpl_CreateVertexBuffer,
6005     IWineD3DDeviceImpl_CreateIndexBuffer,
6006     IWineD3DDeviceImpl_CreateStateBlock,
6007     IWineD3DDeviceImpl_CreateSurface,
6008     IWineD3DDeviceImpl_CreateTexture,
6009     IWineD3DDeviceImpl_CreateVolumeTexture,
6010     IWineD3DDeviceImpl_CreateVolume,
6011     IWineD3DDeviceImpl_CreateCubeTexture,
6012     IWineD3DDeviceImpl_CreateQuery,
6013     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6014     IWineD3DDeviceImpl_CreateVertexDeclaration,
6015     IWineD3DDeviceImpl_CreateVertexShader,
6016     IWineD3DDeviceImpl_CreatePixelShader,
6017     IWineD3DDeviceImpl_CreatePalette,
6018     /*** Odd functions **/
6019     IWineD3DDeviceImpl_Init3D,
6020     IWineD3DDeviceImpl_Uninit3D,
6021     IWineD3DDeviceImpl_SetFullscreen,
6022     IWineD3DDeviceImpl_EnumDisplayModes,
6023     IWineD3DDeviceImpl_EvictManagedResources,
6024     IWineD3DDeviceImpl_GetAvailableTextureMem,
6025     IWineD3DDeviceImpl_GetBackBuffer,
6026     IWineD3DDeviceImpl_GetCreationParameters,
6027     IWineD3DDeviceImpl_GetDeviceCaps,
6028     IWineD3DDeviceImpl_GetDirect3D,
6029     IWineD3DDeviceImpl_GetDisplayMode,
6030     IWineD3DDeviceImpl_SetDisplayMode,
6031     IWineD3DDeviceImpl_GetHWND,
6032     IWineD3DDeviceImpl_SetHWND,
6033     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6034     IWineD3DDeviceImpl_GetRasterStatus,
6035     IWineD3DDeviceImpl_GetSwapChain,
6036     IWineD3DDeviceImpl_Reset,
6037     IWineD3DDeviceImpl_SetDialogBoxMode,
6038     IWineD3DDeviceImpl_SetCursorProperties,
6039     IWineD3DDeviceImpl_SetCursorPosition,
6040     IWineD3DDeviceImpl_ShowCursor,
6041     IWineD3DDeviceImpl_TestCooperativeLevel,
6042     /*** Getters and setters **/
6043     IWineD3DDeviceImpl_SetClipPlane,
6044     IWineD3DDeviceImpl_GetClipPlane,
6045     IWineD3DDeviceImpl_SetClipStatus,
6046     IWineD3DDeviceImpl_GetClipStatus,
6047     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6048     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6049     IWineD3DDeviceImpl_SetDepthStencilSurface,
6050     IWineD3DDeviceImpl_GetDepthStencilSurface,
6051     IWineD3DDeviceImpl_SetFVF,
6052     IWineD3DDeviceImpl_GetFVF,
6053     IWineD3DDeviceImpl_SetGammaRamp,
6054     IWineD3DDeviceImpl_GetGammaRamp,
6055     IWineD3DDeviceImpl_SetIndices,
6056     IWineD3DDeviceImpl_GetIndices,
6057     IWineD3DDeviceImpl_SetBasevertexIndex,
6058     IWineD3DDeviceImpl_SetLight,
6059     IWineD3DDeviceImpl_GetLight,
6060     IWineD3DDeviceImpl_SetLightEnable,
6061     IWineD3DDeviceImpl_GetLightEnable,
6062     IWineD3DDeviceImpl_SetMaterial,
6063     IWineD3DDeviceImpl_GetMaterial,
6064     IWineD3DDeviceImpl_SetNPatchMode,
6065     IWineD3DDeviceImpl_GetNPatchMode,
6066     IWineD3DDeviceImpl_SetPaletteEntries,
6067     IWineD3DDeviceImpl_GetPaletteEntries,
6068     IWineD3DDeviceImpl_SetPixelShader,
6069     IWineD3DDeviceImpl_GetPixelShader,
6070     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6071     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6072     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6073     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6074     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6075     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6076     IWineD3DDeviceImpl_SetRenderState,
6077     IWineD3DDeviceImpl_GetRenderState,
6078     IWineD3DDeviceImpl_SetRenderTarget,
6079     IWineD3DDeviceImpl_GetRenderTarget,
6080     IWineD3DDeviceImpl_SetFrontBackBuffers,
6081     IWineD3DDeviceImpl_SetSamplerState,
6082     IWineD3DDeviceImpl_GetSamplerState,
6083     IWineD3DDeviceImpl_SetScissorRect,
6084     IWineD3DDeviceImpl_GetScissorRect,
6085     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6086     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6087     IWineD3DDeviceImpl_SetStreamSource,
6088     IWineD3DDeviceImpl_GetStreamSource,
6089     IWineD3DDeviceImpl_SetStreamSourceFreq,
6090     IWineD3DDeviceImpl_GetStreamSourceFreq,
6091     IWineD3DDeviceImpl_SetTexture,
6092     IWineD3DDeviceImpl_GetTexture,
6093     IWineD3DDeviceImpl_SetTextureStageState,
6094     IWineD3DDeviceImpl_GetTextureStageState,
6095     IWineD3DDeviceImpl_SetTransform,
6096     IWineD3DDeviceImpl_GetTransform,
6097     IWineD3DDeviceImpl_SetVertexDeclaration,
6098     IWineD3DDeviceImpl_GetVertexDeclaration,
6099     IWineD3DDeviceImpl_SetVertexShader,
6100     IWineD3DDeviceImpl_GetVertexShader,
6101     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6102     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6103     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6104     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6105     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6106     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6107     IWineD3DDeviceImpl_SetViewport,
6108     IWineD3DDeviceImpl_GetViewport,
6109     IWineD3DDeviceImpl_MultiplyTransform,
6110     IWineD3DDeviceImpl_ValidateDevice,
6111     IWineD3DDeviceImpl_ProcessVertices,
6112     /*** State block ***/
6113     IWineD3DDeviceImpl_BeginStateBlock,
6114     IWineD3DDeviceImpl_EndStateBlock,
6115     /*** Scene management ***/
6116     IWineD3DDeviceImpl_BeginScene,
6117     IWineD3DDeviceImpl_EndScene,
6118     IWineD3DDeviceImpl_Present,
6119     IWineD3DDeviceImpl_Clear,
6120     /*** Drawing ***/
6121     IWineD3DDeviceImpl_DrawPrimitive,
6122     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6123     IWineD3DDeviceImpl_DrawPrimitiveUP,
6124     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6125     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6126     IWineD3DDeviceImpl_DrawRectPatch,
6127     IWineD3DDeviceImpl_DrawTriPatch,
6128     IWineD3DDeviceImpl_DeletePatch,
6129     IWineD3DDeviceImpl_ColorFill,
6130     IWineD3DDeviceImpl_UpdateTexture,
6131     IWineD3DDeviceImpl_UpdateSurface,
6132     IWineD3DDeviceImpl_GetFrontBufferData,
6133     IWineD3DDeviceImpl_SetupFullscreenWindow,
6134     IWineD3DDeviceImpl_RestoreWindow,
6135     /*** object tracking ***/
6136     IWineD3DDeviceImpl_ResourceReleased
6137 };
6138
6139
6140 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6141     WINED3DRS_ALPHABLENDENABLE   ,
6142     WINED3DRS_ALPHAFUNC          ,
6143     WINED3DRS_ALPHAREF           ,
6144     WINED3DRS_ALPHATESTENABLE    ,
6145     WINED3DRS_BLENDOP            ,
6146     WINED3DRS_COLORWRITEENABLE   ,
6147     WINED3DRS_DESTBLEND          ,
6148     WINED3DRS_DITHERENABLE       ,
6149     WINED3DRS_FILLMODE           ,
6150     WINED3DRS_FOGDENSITY         ,
6151     WINED3DRS_FOGEND             ,
6152     WINED3DRS_FOGSTART           ,
6153     WINED3DRS_LASTPIXEL          ,
6154     WINED3DRS_SHADEMODE          ,
6155     WINED3DRS_SRCBLEND           ,
6156     WINED3DRS_STENCILENABLE      ,
6157     WINED3DRS_STENCILFAIL        ,
6158     WINED3DRS_STENCILFUNC        ,
6159     WINED3DRS_STENCILMASK        ,
6160     WINED3DRS_STENCILPASS        ,
6161     WINED3DRS_STENCILREF         ,
6162     WINED3DRS_STENCILWRITEMASK   ,
6163     WINED3DRS_STENCILZFAIL       ,
6164     WINED3DRS_TEXTUREFACTOR      ,
6165     WINED3DRS_WRAP0              ,
6166     WINED3DRS_WRAP1              ,
6167     WINED3DRS_WRAP2              ,
6168     WINED3DRS_WRAP3              ,
6169     WINED3DRS_WRAP4              ,
6170     WINED3DRS_WRAP5              ,
6171     WINED3DRS_WRAP6              ,
6172     WINED3DRS_WRAP7              ,
6173     WINED3DRS_ZENABLE            ,
6174     WINED3DRS_ZFUNC              ,
6175     WINED3DRS_ZWRITEENABLE
6176 };
6177
6178 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6179     WINED3DTSS_ADDRESSW              ,
6180     WINED3DTSS_ALPHAARG0             ,
6181     WINED3DTSS_ALPHAARG1             ,
6182     WINED3DTSS_ALPHAARG2             ,
6183     WINED3DTSS_ALPHAOP               ,
6184     WINED3DTSS_BUMPENVLOFFSET        ,
6185     WINED3DTSS_BUMPENVLSCALE         ,
6186     WINED3DTSS_BUMPENVMAT00          ,
6187     WINED3DTSS_BUMPENVMAT01          ,
6188     WINED3DTSS_BUMPENVMAT10          ,
6189     WINED3DTSS_BUMPENVMAT11          ,
6190     WINED3DTSS_COLORARG0             ,
6191     WINED3DTSS_COLORARG1             ,
6192     WINED3DTSS_COLORARG2             ,
6193     WINED3DTSS_COLOROP               ,
6194     WINED3DTSS_RESULTARG             ,
6195     WINED3DTSS_TEXCOORDINDEX         ,
6196     WINED3DTSS_TEXTURETRANSFORMFLAGS
6197 };
6198
6199 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6200     WINED3DSAMP_ADDRESSU         ,
6201     WINED3DSAMP_ADDRESSV         ,
6202     WINED3DSAMP_ADDRESSW         ,
6203     WINED3DSAMP_BORDERCOLOR      ,
6204     WINED3DSAMP_MAGFILTER        ,
6205     WINED3DSAMP_MINFILTER        ,
6206     WINED3DSAMP_MIPFILTER        ,
6207     WINED3DSAMP_MIPMAPLODBIAS    ,
6208     WINED3DSAMP_MAXMIPLEVEL      ,
6209     WINED3DSAMP_MAXANISOTROPY    ,
6210     WINED3DSAMP_SRGBTEXTURE      ,
6211     WINED3DSAMP_ELEMENTINDEX
6212 };
6213
6214 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6215     WINED3DRS_AMBIENT                       ,
6216     WINED3DRS_AMBIENTMATERIALSOURCE         ,
6217     WINED3DRS_CLIPPING                      ,
6218     WINED3DRS_CLIPPLANEENABLE               ,
6219     WINED3DRS_COLORVERTEX                   ,
6220     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
6221     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
6222     WINED3DRS_FOGDENSITY                    ,
6223     WINED3DRS_FOGEND                        ,
6224     WINED3DRS_FOGSTART                      ,
6225     WINED3DRS_FOGTABLEMODE                  ,
6226     WINED3DRS_FOGVERTEXMODE                 ,
6227     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
6228     WINED3DRS_LIGHTING                      ,
6229     WINED3DRS_LOCALVIEWER                   ,
6230     WINED3DRS_MULTISAMPLEANTIALIAS          ,
6231     WINED3DRS_MULTISAMPLEMASK               ,
6232     WINED3DRS_NORMALIZENORMALS              ,
6233     WINED3DRS_PATCHEDGESTYLE                ,
6234     WINED3DRS_POINTSCALE_A                  ,
6235     WINED3DRS_POINTSCALE_B                  ,
6236     WINED3DRS_POINTSCALE_C                  ,
6237     WINED3DRS_POINTSCALEENABLE              ,
6238     WINED3DRS_POINTSIZE                     ,
6239     WINED3DRS_POINTSIZE_MAX                 ,
6240     WINED3DRS_POINTSIZE_MIN                 ,
6241     WINED3DRS_POINTSPRITEENABLE             ,
6242     WINED3DRS_RANGEFOGENABLE                ,
6243     WINED3DRS_SPECULARMATERIALSOURCE        ,
6244     WINED3DRS_TWEENFACTOR                   ,
6245     WINED3DRS_VERTEXBLEND
6246 };
6247
6248 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6249     WINED3DTSS_TEXCOORDINDEX         ,
6250     WINED3DTSS_TEXTURETRANSFORMFLAGS
6251 };
6252
6253 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6254     WINED3DSAMP_DMAPOFFSET
6255 };
6256
6257 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
6258     DWORD rep = StateTable[state].representative;
6259     DWORD idx;
6260     BYTE shift;
6261     UINT i;
6262     WineD3DContext *context;
6263
6264     if(!rep) return;
6265     for(i = 0; i < This->numContexts; i++) {
6266         context = This->contexts[i];
6267         if(isStateDirty(context, rep)) continue;
6268
6269         context->dirtyArray[context->numDirtyEntries++] = rep;
6270         idx = rep >> 5;
6271         shift = rep & 0x1f;
6272         context->isStateDirty[idx] |= (1 << shift);
6273     }
6274 }