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