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