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