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