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