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