wined3d: Make sure the FBO doesn't have any depth attachments in color_fill_fbo(...
[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     This->shader_backend->shader_destroy_depth_blt(iface);
2283     This->shader_backend->shader_free_private(iface);
2284
2285     /* Release the update stateblock */
2286     if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
2287         if(This->updateStateBlock != This->stateBlock)
2288             FIXME("(%p) Something's still holding the Update stateblock\n",This);
2289     }
2290     This->updateStateBlock = NULL;
2291
2292     { /* because were not doing proper internal refcounts releasing the primary state block
2293         causes recursion with the extra checks in ResourceReleased, to avoid this we have
2294         to set this->stateBlock = NULL; first */
2295         IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
2296         This->stateBlock = NULL;
2297
2298         /* Release the stateblock */
2299         if(IWineD3DStateBlock_Release(stateBlock) > 0){
2300             FIXME("(%p) Something's still holding the Update stateblock\n",This);
2301         }
2302     }
2303
2304     /* Release the buffers (with sanity checks)*/
2305     TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
2306     if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
2307         if(This->auto_depth_stencil_buffer != This->stencilBufferTarget)
2308             FIXME("(%p) Something's still holding the stencilBufferTarget\n",This);
2309     }
2310     This->stencilBufferTarget = NULL;
2311
2312     TRACE("Releasing the render target at %p\n", This->render_targets[0]);
2313     if(IWineD3DSurface_Release(This->render_targets[0]) >0){
2314           /* This check is a bit silly, it should be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2315     }
2316     TRACE("Setting rendertarget to NULL\n");
2317     This->render_targets[0] = NULL;
2318
2319     if (This->auto_depth_stencil_buffer) {
2320         if(D3DCB_DestroyDepthStencilSurface(This->auto_depth_stencil_buffer) > 0) {
2321             FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This);
2322         }
2323         This->auto_depth_stencil_buffer = NULL;
2324     }
2325
2326     for(i=0; i < This->NumberOfSwapChains; i++) {
2327         TRACE("Releasing the implicit swapchain %d\n", i);
2328         if (D3DCB_DestroySwapChain(This->swapchains[i])  > 0) {
2329             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
2330         }
2331     }
2332
2333     HeapFree(GetProcessHeap(), 0, This->swapchains);
2334     This->swapchains = NULL;
2335     This->NumberOfSwapChains = 0;
2336
2337     for (i = 0; i < This->NumberOfPalettes; i++) HeapFree(GetProcessHeap(), 0, This->palettes[i]);
2338     HeapFree(GetProcessHeap(), 0, This->palettes);
2339     This->palettes = NULL;
2340     This->NumberOfPalettes = 0;
2341
2342     HeapFree(GetProcessHeap(), 0, This->render_targets);
2343     HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments);
2344     HeapFree(GetProcessHeap(), 0, This->draw_buffers);
2345     This->render_targets = NULL;
2346     This->fbo_color_attachments = NULL;
2347     This->draw_buffers = NULL;
2348
2349     This->d3d_initialized = FALSE;
2350     return WINED3D_OK;
2351 }
2352
2353 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
2354     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2355     TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
2356
2357     /* Setup the window for fullscreen mode */
2358     if(fullscreen && !This->ddraw_fullscreen) {
2359         IWineD3DDeviceImpl_SetupFullscreenWindow(iface, This->ddraw_window);
2360     } else if(!fullscreen && This->ddraw_fullscreen) {
2361         IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
2362     }
2363
2364     /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2365      * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2366      * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
2367      * separately.
2368      */
2369     This->ddraw_fullscreen = fullscreen;
2370 }
2371
2372 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
2373  * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
2374  * CreateDevice if D3DCREATE_MULTITHREADED is passed.
2375  *
2376  * There is no way to deactivate thread safety once it is enabled.
2377  */
2378 static void WINAPI IWineD3DDeviceImpl_SetMultithreaded(IWineD3DDevice *iface) {
2379     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2380
2381     /*For now just store the flag(needed in case of ddraw) */
2382     This->createParms.BehaviorFlags |= WINED3DCREATE_MULTITHREADED;
2383
2384     return;
2385 }
2386
2387 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2388     DEVMODEW devmode;
2389     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2390     LONG ret;
2391     const StaticPixelFormatDesc *formatDesc  = getFormatDescEntry(pMode->Format, NULL, NULL);
2392     RECT clip_rc;
2393
2394     TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2395
2396     /* Resize the screen even without a window:
2397      * The app could have unset it with SetCooperativeLevel, but not called
2398      * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2399      * but we don't have any hwnd
2400      */
2401
2402     memset(&devmode, 0, sizeof(devmode));
2403     devmode.dmSize = sizeof(devmode);
2404     devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2405     devmode.dmBitsPerPel = formatDesc->bpp * 8;
2406     devmode.dmPelsWidth  = pMode->Width;
2407     devmode.dmPelsHeight = pMode->Height;
2408
2409     devmode.dmDisplayFrequency = pMode->RefreshRate;
2410     if (pMode->RefreshRate != 0)  {
2411         devmode.dmFields |= DM_DISPLAYFREQUENCY;
2412     }
2413
2414     /* Only change the mode if necessary */
2415     if( (This->ddraw_width == pMode->Width) &&
2416         (This->ddraw_height == pMode->Height) &&
2417         (This->ddraw_format == pMode->Format) &&
2418         (pMode->RefreshRate == 0) ) {
2419         return WINED3D_OK;
2420     }
2421
2422     ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2423     if (ret != DISP_CHANGE_SUCCESSFUL) {
2424         if(devmode.dmDisplayFrequency != 0) {
2425             WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2426             devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2427             devmode.dmDisplayFrequency = 0;
2428             ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2429         }
2430         if(ret != DISP_CHANGE_SUCCESSFUL) {
2431             return WINED3DERR_NOTAVAILABLE;
2432         }
2433     }
2434
2435     /* Store the new values */
2436     This->ddraw_width = pMode->Width;
2437     This->ddraw_height = pMode->Height;
2438     This->ddraw_format = pMode->Format;
2439
2440     /* Only do this with a window of course, and only if we're fullscreened */
2441     if(This->ddraw_window && This->ddraw_fullscreen)
2442       MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2443
2444     /* And finally clip mouse to our screen */
2445     SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
2446     ClipCursor(&clip_rc);
2447
2448     return WINED3D_OK;
2449 }
2450
2451 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2452    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2453    *ppD3D= This->wineD3D;
2454    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
2455    IWineD3D_AddRef(*ppD3D);
2456    return WINED3D_OK;
2457 }
2458
2459 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2460     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2461
2462     TRACE("(%p) : simulating %dMB, returning %dMB left\n",  This,
2463          (This->adapter->TextureRam/(1024*1024)),
2464          ((This->adapter->TextureRam - This->adapter->UsedTextureRam) / (1024*1024)));
2465     /* return simulated texture memory left */
2466     return (This->adapter->TextureRam - This->adapter->UsedTextureRam);
2467 }
2468
2469
2470
2471 /*****
2472  * Get / Set FVF
2473  *****/
2474 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2475     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2476
2477     /* Update the current state block */
2478     This->updateStateBlock->changed.fvf      = TRUE;
2479
2480     if(This->updateStateBlock->fvf == fvf) {
2481         TRACE("Application is setting the old fvf over, nothing to do\n");
2482         return WINED3D_OK;
2483     }
2484
2485     This->updateStateBlock->fvf              = fvf;
2486     TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2487     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
2488     return WINED3D_OK;
2489 }
2490
2491
2492 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2493     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2494     TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2495     *pfvf = This->stateBlock->fvf;
2496     return WINED3D_OK;
2497 }
2498
2499 /*****
2500  * Get / Set Stream Source
2501  *****/
2502 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2503         IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
2504     IWineD3DVertexBuffer     *oldSrc;
2505
2506     if (StreamNumber >= MAX_STREAMS) {
2507         WARN("Stream out of range %d\n", StreamNumber);
2508         return WINED3DERR_INVALIDCALL;
2509     } else if(OffsetInBytes & 0x3) {
2510         WARN("OffsetInBytes is not 4 byte aligned: %d\n", OffsetInBytes);
2511         return WINED3DERR_INVALIDCALL;
2512     }
2513
2514     oldSrc = This->updateStateBlock->streamSource[StreamNumber];
2515     TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This, StreamNumber, oldSrc, pStreamData, OffsetInBytes, Stride);
2516
2517     This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2518
2519     if(oldSrc == pStreamData &&
2520        This->updateStateBlock->streamStride[StreamNumber] == Stride &&
2521        This->updateStateBlock->streamOffset[StreamNumber] == OffsetInBytes) {
2522        TRACE("Application is setting the old values over, nothing to do\n");
2523        return WINED3D_OK;
2524     }
2525
2526     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
2527     if (pStreamData) {
2528         This->updateStateBlock->streamStride[StreamNumber]     = Stride;
2529         This->updateStateBlock->streamOffset[StreamNumber]     = OffsetInBytes;
2530     }
2531
2532     /* Handle recording of state blocks */
2533     if (This->isRecordingState) {
2534         TRACE("Recording... not performing anything\n");
2535         if(pStreamData) IWineD3DVertexBuffer_AddRef(pStreamData);
2536         if(oldSrc) IWineD3DVertexBuffer_Release(oldSrc);
2537         return WINED3D_OK;
2538     }
2539
2540     /* Need to do a getParent and pass the references up */
2541     /* MSDN says ..... When an application no longer holds a reference to this interface, the interface will automatically be freed.
2542     which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2543     so for now, just count internally   */
2544     if (pStreamData != NULL) {
2545         IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2546         InterlockedIncrement(&vbImpl->bindCount);
2547         IWineD3DVertexBuffer_AddRef(pStreamData);
2548     }
2549     if (oldSrc != NULL) {
2550         InterlockedDecrement(&((IWineD3DVertexBufferImpl *) oldSrc)->bindCount);
2551         IWineD3DVertexBuffer_Release(oldSrc);
2552     }
2553
2554     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2555
2556     return WINED3D_OK;
2557 }
2558
2559 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2560     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2561
2562     TRACE("(%p) : StreamNo: %u, Stream (%p), Offset %u, Stride %u\n", This, StreamNumber,
2563            This->stateBlock->streamSource[StreamNumber],
2564            This->stateBlock->streamOffset[StreamNumber],
2565            This->stateBlock->streamStride[StreamNumber]);
2566
2567     if (StreamNumber >= MAX_STREAMS) {
2568         WARN("Stream out of range %d\n", StreamNumber);
2569         return WINED3DERR_INVALIDCALL;
2570     }
2571     *pStream = This->stateBlock->streamSource[StreamNumber];
2572     *pStride = This->stateBlock->streamStride[StreamNumber];
2573     if (pOffset) {
2574         *pOffset = This->stateBlock->streamOffset[StreamNumber];
2575     }
2576
2577     if (*pStream != NULL) {
2578         IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2579     }
2580     return WINED3D_OK;
2581 }
2582
2583 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
2584     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2585     UINT oldFlags = This->updateStateBlock->streamFlags[StreamNumber];
2586     UINT oldFreq = This->updateStateBlock->streamFreq[StreamNumber];
2587
2588     /* Verify input at least in d3d9 this is invalid*/
2589     if( (Divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && (Divider & WINED3DSTREAMSOURCE_INDEXEDDATA)){
2590         WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL\n");
2591         return WINED3DERR_INVALIDCALL;
2592     }
2593     if( (Divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && StreamNumber == 0 ){
2594         WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL\n");
2595         return WINED3DERR_INVALIDCALL;
2596     }
2597     if( Divider == 0 ){
2598         WARN("Divider is 0, returning D3DERR_INVALIDCALL\n");
2599         return WINED3DERR_INVALIDCALL;
2600     }
2601
2602     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2603     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
2604
2605     This->updateStateBlock->changed.streamFreq[StreamNumber]  = TRUE;
2606     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
2607
2608     if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq ||
2609        This->updateStateBlock->streamFlags[StreamNumber] != oldFlags) {
2610         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2611     }
2612
2613     return WINED3D_OK;
2614 }
2615
2616 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
2617     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2618
2619     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2620     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2621
2622     TRACE("(%p) : returning %d\n", This, *Divider);
2623
2624     return WINED3D_OK;
2625 }
2626
2627 /*****
2628  * Get / Set & Multiply Transform
2629  *****/
2630 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2631     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2632
2633     /* Most of this routine, comments included copied from ddraw tree initially: */
2634     TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2635
2636     /* Handle recording of state blocks */
2637     if (This->isRecordingState) {
2638         TRACE("Recording... not performing anything\n");
2639         This->updateStateBlock->changed.transform[d3dts] = TRUE;
2640         This->updateStateBlock->transforms[d3dts] = *lpmatrix;
2641         return WINED3D_OK;
2642     }
2643
2644     /*
2645      * If the new matrix is the same as the current one,
2646      * we cut off any further processing. this seems to be a reasonable
2647      * optimization because as was noticed, some apps (warcraft3 for example)
2648      * tend towards setting the same matrix repeatedly for some reason.
2649      *
2650      * From here on we assume that the new matrix is different, wherever it matters.
2651      */
2652     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2653         TRACE("The app is setting the same matrix over again\n");
2654         return WINED3D_OK;
2655     } else {
2656         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2657     }
2658
2659     /*
2660        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2661        where ViewMat = Camera space, WorldMat = world space.
2662
2663        In OpenGL, camera and world space is combined into GL_MODELVIEW
2664        matrix.  The Projection matrix stay projection matrix.
2665      */
2666
2667     /* Capture the times we can just ignore the change for now */
2668     if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrix */
2669         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2670         /* Handled by the state manager */
2671     }
2672
2673     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2674     return WINED3D_OK;
2675
2676 }
2677 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2678     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2679     TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2680     *pMatrix = This->stateBlock->transforms[State];
2681     return WINED3D_OK;
2682 }
2683
2684 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2685     WINED3DMATRIX *mat = NULL;
2686     WINED3DMATRIX temp;
2687
2688     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2689      * below means it will be recorded in a state block change, but it
2690      * works regardless where it is recorded.
2691      * If this is found to be wrong, change to StateBlock.
2692      */
2693     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2694     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2695
2696     if (State < HIGHEST_TRANSFORMSTATE)
2697     {
2698         mat = &This->updateStateBlock->transforms[State];
2699     } else {
2700         FIXME("Unhandled transform state!!\n");
2701     }
2702
2703     multiply_matrix(&temp, mat, pMatrix);
2704
2705     /* Apply change via set transform - will reapply to eg. lights this way */
2706     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2707 }
2708
2709 /*****
2710  * Get / Set Light
2711  *****/
2712 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2713    you can reference any indexes you want as long as that number max are enabled at any
2714    one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2715    However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2716    but when recording, just build a chain pretty much of commands to be replayed.                  */
2717
2718 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2719     float rho;
2720     PLIGHTINFOEL *object = NULL;
2721     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2722     struct list *e;
2723
2724     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2725     TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This, Index, pLight, Hi);
2726
2727     /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2728      * the gl driver.
2729      */
2730     if(!pLight) {
2731         WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2732         return WINED3DERR_INVALIDCALL;
2733     }
2734
2735     switch(pLight->Type) {
2736         case WINED3DLIGHT_POINT:
2737         case WINED3DLIGHT_SPOT:
2738         case WINED3DLIGHT_PARALLELPOINT:
2739         case WINED3DLIGHT_GLSPOT:
2740             /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2741              * most wanted
2742              */
2743             if(pLight->Attenuation0 < 0.0 || pLight->Attenuation1 < 0.0 || pLight->Attenuation2 < 0.0) {
2744                 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2745                 return WINED3DERR_INVALIDCALL;
2746             }
2747             break;
2748
2749         case WINED3DLIGHT_DIRECTIONAL:
2750             /* Ignores attenuation */
2751             break;
2752
2753         default:
2754         WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2755         return WINED3DERR_INVALIDCALL;
2756     }
2757
2758     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2759         object = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2760         if(object->OriginalIndex == Index) break;
2761         object = NULL;
2762     }
2763
2764     if(!object) {
2765         TRACE("Adding new light\n");
2766         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2767         if(!object) {
2768             ERR("Out of memory error when allocating a light\n");
2769             return E_OUTOFMEMORY;
2770         }
2771         list_add_head(&This->updateStateBlock->lightMap[Hi], &object->entry);
2772         object->glIndex = -1;
2773         object->OriginalIndex = Index;
2774         object->changed = TRUE;
2775     }
2776
2777     /* Initialize the object */
2778     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,
2779           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2780           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2781           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2782     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2783           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2784     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2785
2786     /* Save away the information */
2787     object->OriginalParms = *pLight;
2788
2789     switch (pLight->Type) {
2790     case WINED3DLIGHT_POINT:
2791         /* Position */
2792         object->lightPosn[0] = pLight->Position.x;
2793         object->lightPosn[1] = pLight->Position.y;
2794         object->lightPosn[2] = pLight->Position.z;
2795         object->lightPosn[3] = 1.0f;
2796         object->cutoff = 180.0f;
2797         /* FIXME: Range */
2798         break;
2799
2800     case WINED3DLIGHT_DIRECTIONAL:
2801         /* Direction */
2802         object->lightPosn[0] = -pLight->Direction.x;
2803         object->lightPosn[1] = -pLight->Direction.y;
2804         object->lightPosn[2] = -pLight->Direction.z;
2805         object->lightPosn[3] = 0.0;
2806         object->exponent     = 0.0f;
2807         object->cutoff       = 180.0f;
2808         break;
2809
2810     case WINED3DLIGHT_SPOT:
2811         /* Position */
2812         object->lightPosn[0] = pLight->Position.x;
2813         object->lightPosn[1] = pLight->Position.y;
2814         object->lightPosn[2] = pLight->Position.z;
2815         object->lightPosn[3] = 1.0;
2816
2817         /* Direction */
2818         object->lightDirn[0] = pLight->Direction.x;
2819         object->lightDirn[1] = pLight->Direction.y;
2820         object->lightDirn[2] = pLight->Direction.z;
2821         object->lightDirn[3] = 1.0;
2822
2823         /*
2824          * opengl-ish and d3d-ish spot lights use too different models for the
2825          * light "intensity" as a function of the angle towards the main light direction,
2826          * so we only can approximate very roughly.
2827          * however spot lights are rather rarely used in games (if ever used at all).
2828          * furthermore if still used, probably nobody pays attention to such details.
2829          */
2830         if (pLight->Falloff == 0) {
2831             /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
2832              * falloff resp. exponent parameter as an exponent, so the spot light lighting
2833              * will always be 1.0 for both of them, and we don't have to care for the
2834              * rest of the rather complex calculation
2835              */
2836             object->exponent = 0;
2837         } else {
2838             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2839             if (rho < 0.0001) rho = 0.0001f;
2840             object->exponent = -0.3/log(cos(rho/2));
2841         }
2842         if (object->exponent > 128.0) {
2843                 object->exponent = 128.0;
2844         }
2845         object->cutoff = pLight->Phi*90/M_PI;
2846
2847         /* FIXME: Range */
2848         break;
2849
2850     default:
2851         FIXME("Unrecognized light type %d\n", pLight->Type);
2852     }
2853
2854     /* Update the live definitions if the light is currently assigned a glIndex */
2855     if (object->glIndex != -1 && !This->isRecordingState) {
2856         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(object->glIndex));
2857     }
2858     return WINED3D_OK;
2859 }
2860
2861 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2862     PLIGHTINFOEL *lightInfo = NULL;
2863     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2864     DWORD Hi = LIGHTMAP_HASHFUNC(Index);
2865     struct list *e;
2866     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2867
2868     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2869         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2870         if(lightInfo->OriginalIndex == Index) break;
2871         lightInfo = NULL;
2872     }
2873
2874     if (lightInfo == NULL) {
2875         TRACE("Light information requested but light not defined\n");
2876         return WINED3DERR_INVALIDCALL;
2877     }
2878
2879     *pLight = lightInfo->OriginalParms;
2880     return WINED3D_OK;
2881 }
2882
2883 /*****
2884  * Get / Set Light Enable
2885  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2886  *****/
2887 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2888     PLIGHTINFOEL *lightInfo = NULL;
2889     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2890     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2891     struct list *e;
2892     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2893
2894     /* Tests show true = 128...not clear why */
2895     Enable = Enable? 128: 0;
2896
2897     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2898         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2899         if(lightInfo->OriginalIndex == Index) break;
2900         lightInfo = NULL;
2901     }
2902     TRACE("Found light: %p\n", lightInfo);
2903
2904     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2905     if (lightInfo == NULL) {
2906
2907         TRACE("Light enabled requested but light not defined, so defining one!\n");
2908         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2909
2910         /* Search for it again! Should be fairly quick as near head of list */
2911         LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2912             lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2913             if(lightInfo->OriginalIndex == Index) break;
2914             lightInfo = NULL;
2915         }
2916         if (lightInfo == NULL) {
2917             FIXME("Adding default lights has failed dismally\n");
2918             return WINED3DERR_INVALIDCALL;
2919         }
2920     }
2921
2922     lightInfo->enabledChanged = TRUE;
2923     if(!Enable) {
2924         if(lightInfo->glIndex != -1) {
2925             if(!This->isRecordingState) {
2926                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(lightInfo->glIndex));
2927             }
2928
2929             This->stateBlock->activeLights[lightInfo->glIndex] = NULL;
2930             lightInfo->glIndex = -1;
2931         } else {
2932             TRACE("Light already disabled, nothing to do\n");
2933         }
2934         lightInfo->enabled = FALSE;
2935     } else {
2936         lightInfo->enabled = TRUE;
2937         if (lightInfo->glIndex != -1) {
2938             /* nop */
2939             TRACE("Nothing to do as light was enabled\n");
2940         } else {
2941             int i;
2942             /* Find a free gl light */
2943             for(i = 0; i < This->maxConcurrentLights; i++) {
2944                 if(This->stateBlock->activeLights[i] == NULL) {
2945                     This->stateBlock->activeLights[i] = lightInfo;
2946                     lightInfo->glIndex = i;
2947                     break;
2948                 }
2949             }
2950             if(lightInfo->glIndex == -1) {
2951                 /* Our tests show that Windows returns D3D_OK in this situation, even with
2952                  * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
2953                  * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
2954                  * as well for those lights.
2955                  *
2956                  * TODO: Test how this affects rendering
2957                  */
2958                 FIXME("Too many concurrently active lights\n");
2959                 return WINED3D_OK;
2960             }
2961
2962             /* i == lightInfo->glIndex */
2963             if(!This->isRecordingState) {
2964                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i));
2965             }
2966         }
2967     }
2968
2969     return WINED3D_OK;
2970 }
2971
2972 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2973
2974     PLIGHTINFOEL *lightInfo = NULL;
2975     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2976     struct list *e;
2977     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2978     TRACE("(%p) : for idx(%d)\n", This, Index);
2979
2980     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2981         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2982         if(lightInfo->OriginalIndex == Index) break;
2983         lightInfo = NULL;
2984     }
2985
2986     if (lightInfo == NULL) {
2987         TRACE("Light enabled state requested but light not defined\n");
2988         return WINED3DERR_INVALIDCALL;
2989     }
2990     /* true is 128 according to SetLightEnable */
2991     *pEnable = lightInfo->enabled ? 128 : 0;
2992     return WINED3D_OK;
2993 }
2994
2995 /*****
2996  * Get / Set Clip Planes
2997  *****/
2998 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2999     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3000     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
3001
3002     /* Validate Index */
3003     if (Index >= GL_LIMITS(clipplanes)) {
3004         TRACE("Application has requested clipplane this device doesn't support\n");
3005         return WINED3DERR_INVALIDCALL;
3006     }
3007
3008     This->updateStateBlock->changed.clipplane[Index] = TRUE;
3009
3010     if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
3011        This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
3012        This->updateStateBlock->clipplane[Index][2] == pPlane[2] &&
3013        This->updateStateBlock->clipplane[Index][3] == pPlane[3]) {
3014         TRACE("Application is setting old values over, nothing to do\n");
3015         return WINED3D_OK;
3016     }
3017
3018     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
3019     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
3020     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
3021     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
3022
3023     /* Handle recording of state blocks */
3024     if (This->isRecordingState) {
3025         TRACE("Recording... not performing anything\n");
3026         return WINED3D_OK;
3027     }
3028
3029     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_CLIPPLANE(Index));
3030
3031     return WINED3D_OK;
3032 }
3033
3034 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
3035     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3036     TRACE("(%p) : for idx %d\n", This, Index);
3037
3038     /* Validate Index */
3039     if (Index >= GL_LIMITS(clipplanes)) {
3040         TRACE("Application has requested clipplane this device doesn't support\n");
3041         return WINED3DERR_INVALIDCALL;
3042     }
3043
3044     pPlane[0] = This->stateBlock->clipplane[Index][0];
3045     pPlane[1] = This->stateBlock->clipplane[Index][1];
3046     pPlane[2] = This->stateBlock->clipplane[Index][2];
3047     pPlane[3] = This->stateBlock->clipplane[Index][3];
3048     return WINED3D_OK;
3049 }
3050
3051 /*****
3052  * Get / Set Clip Plane Status
3053  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3054  *****/
3055 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
3056     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3057     FIXME("(%p) : stub\n", This);
3058     if (NULL == pClipStatus) {
3059       return WINED3DERR_INVALIDCALL;
3060     }
3061     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3062     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3063     return WINED3D_OK;
3064 }
3065
3066 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
3067     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3068     FIXME("(%p) : stub\n", This);
3069     if (NULL == pClipStatus) {
3070       return WINED3DERR_INVALIDCALL;
3071     }
3072     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
3073     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
3074     return WINED3D_OK;
3075 }
3076
3077 /*****
3078  * Get / Set Material
3079  *****/
3080 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
3081     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3082
3083     if (!pMaterial) return WINED3DERR_INVALIDCALL;
3084
3085     This->updateStateBlock->changed.material = TRUE;
3086     This->updateStateBlock->material = *pMaterial;
3087
3088     /* Handle recording of state blocks */
3089     if (This->isRecordingState) {
3090         TRACE("Recording... not performing anything\n");
3091         return WINED3D_OK;
3092     }
3093
3094     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_MATERIAL);
3095     return WINED3D_OK;
3096 }
3097
3098 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
3099     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3100     *pMaterial = This->updateStateBlock->material;
3101     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
3102         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
3103     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
3104         pMaterial->Ambient.b, pMaterial->Ambient.a);
3105     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
3106         pMaterial->Specular.b, pMaterial->Specular.a);
3107     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
3108         pMaterial->Emissive.b, pMaterial->Emissive.a);
3109     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
3110
3111     return WINED3D_OK;
3112 }
3113
3114 /*****
3115  * Get / Set Indices
3116  *****/
3117 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData) {
3118     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
3119     IWineD3DIndexBuffer *oldIdxs;
3120
3121     TRACE("(%p) : Setting to %p\n", This, pIndexData);
3122     oldIdxs = This->updateStateBlock->pIndexData;
3123
3124     This->updateStateBlock->changed.indices = TRUE;
3125     This->updateStateBlock->pIndexData = pIndexData;
3126
3127     /* Handle recording of state blocks */
3128     if (This->isRecordingState) {
3129         TRACE("Recording... not performing anything\n");
3130         if(pIndexData) IWineD3DIndexBuffer_AddRef(pIndexData);
3131         if(oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
3132         return WINED3D_OK;
3133     }
3134
3135     if(oldIdxs != pIndexData) {
3136         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
3137         if(pIndexData) IWineD3DIndexBuffer_AddRef(pIndexData);
3138         if(oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
3139     }
3140     return WINED3D_OK;
3141 }
3142
3143 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData) {
3144     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3145
3146     *ppIndexData = This->stateBlock->pIndexData;
3147
3148     /* up ref count on ppindexdata */
3149     if (*ppIndexData) {
3150         IWineD3DIndexBuffer_AddRef(*ppIndexData);
3151         TRACE("(%p) index data set to %p\n", This, ppIndexData);
3152     }else{
3153         TRACE("(%p) No index data set\n", This);
3154     }
3155     TRACE("Returning %p\n", *ppIndexData);
3156
3157     return WINED3D_OK;
3158 }
3159
3160 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
3161 static HRESULT WINAPI IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice *iface, INT BaseIndex) {
3162     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3163     TRACE("(%p)->(%d)\n", This, BaseIndex);
3164
3165     if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
3166         TRACE("Application is setting the old value over, nothing to do\n");
3167         return WINED3D_OK;
3168     }
3169
3170     This->updateStateBlock->baseVertexIndex = BaseIndex;
3171
3172     if (This->isRecordingState) {
3173         TRACE("Recording... not performing anything\n");
3174         return WINED3D_OK;
3175     }
3176     /* The base vertex index affects the stream sources */
3177     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
3178     return WINED3D_OK;
3179 }
3180
3181 static HRESULT WINAPI IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice *iface, INT* base_index) {
3182     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3183     TRACE("(%p) : base_index %p\n", This, base_index);
3184
3185     *base_index = This->stateBlock->baseVertexIndex;
3186
3187     TRACE("Returning %u\n", *base_index);
3188
3189     return WINED3D_OK;
3190 }
3191
3192 /*****
3193  * Get / Set Viewports
3194  *****/
3195 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3196     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3197
3198     TRACE("(%p)\n", This);
3199     This->updateStateBlock->changed.viewport = TRUE;
3200     This->updateStateBlock->viewport = *pViewport;
3201
3202     /* Handle recording of state blocks */
3203     if (This->isRecordingState) {
3204         TRACE("Recording... not performing anything\n");
3205         return WINED3D_OK;
3206     }
3207
3208     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3209           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3210
3211     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
3212     return WINED3D_OK;
3213
3214 }
3215
3216 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3217     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3218     TRACE("(%p)\n", This);
3219     *pViewport = This->stateBlock->viewport;
3220     return WINED3D_OK;
3221 }
3222
3223 /*****
3224  * Get / Set Render States
3225  * TODO: Verify against dx9 definitions
3226  *****/
3227 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
3228
3229     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
3230     DWORD oldValue = This->stateBlock->renderState[State];
3231
3232     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3233
3234     This->updateStateBlock->changed.renderState[State] = TRUE;
3235     This->updateStateBlock->renderState[State] = Value;
3236
3237     /* Handle recording of state blocks */
3238     if (This->isRecordingState) {
3239         TRACE("Recording... not performing anything\n");
3240         return WINED3D_OK;
3241     }
3242
3243     /* Compared here and not before the assignment to allow proper stateblock recording */
3244     if(Value == oldValue) {
3245         TRACE("Application is setting the old value over, nothing to do\n");
3246     } else {
3247         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
3248     }
3249
3250     return WINED3D_OK;
3251 }
3252
3253 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
3254     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3255     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
3256     *pValue = This->stateBlock->renderState[State];
3257     return WINED3D_OK;
3258 }
3259
3260 /*****
3261  * Get / Set Sampler States
3262  * TODO: Verify against dx9 definitions
3263  *****/
3264
3265 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3266     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3267     DWORD oldValue;
3268
3269     TRACE("(%p) : Sampler %#x, Type %s (%#x), Value %#x\n",
3270             This, Sampler, debug_d3dsamplerstate(Type), Type, Value);
3271
3272     if (Sampler >= WINED3DVERTEXTEXTURESAMPLER0 && Sampler <= WINED3DVERTEXTEXTURESAMPLER3) {
3273         Sampler -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
3274     }
3275
3276     if (Sampler >= sizeof(This->stateBlock->samplerState)/sizeof(This->stateBlock->samplerState[0])) {
3277         ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler);
3278         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
3279     }
3280     /**
3281     * SetSampler is designed to allow for more than the standard up to 8 textures
3282     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
3283     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3284     *
3285     * http://developer.nvidia.com/object/General_FAQ.html#t6
3286     *
3287     * There are two new settings for GForce
3288     * the sampler one:
3289     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3290     * and the texture one:
3291     * GL_MAX_TEXTURE_COORDS_ARB.
3292     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3293      ******************/
3294
3295     oldValue = This->stateBlock->samplerState[Sampler][Type];
3296     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
3297     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3298
3299     /* Handle recording of state blocks */
3300     if (This->isRecordingState) {
3301         TRACE("Recording... not performing anything\n");
3302         return WINED3D_OK;
3303     }
3304
3305     if(oldValue == Value) {
3306         TRACE("Application is setting the old value over, nothing to do\n");
3307         return WINED3D_OK;
3308     }
3309
3310     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
3311
3312     return WINED3D_OK;
3313 }
3314
3315 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3316     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3317
3318     TRACE("(%p) : Sampler %#x, Type %s (%#x)\n",
3319             This, Sampler, debug_d3dsamplerstate(Type), Type);
3320
3321     if (Sampler >= WINED3DVERTEXTEXTURESAMPLER0 && Sampler <= WINED3DVERTEXTEXTURESAMPLER3) {
3322         Sampler -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
3323     }
3324
3325     if (Sampler >= sizeof(This->stateBlock->samplerState)/sizeof(This->stateBlock->samplerState[0])) {
3326         ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler);
3327         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
3328     }
3329     *Value = This->stateBlock->samplerState[Sampler][Type];
3330     TRACE("(%p) : Returning %#x\n", This, *Value);
3331
3332     return WINED3D_OK;
3333 }
3334
3335 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3336     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3337
3338     This->updateStateBlock->changed.scissorRect = TRUE;
3339     if(EqualRect(&This->updateStateBlock->scissorRect, pRect)) {
3340         TRACE("App is setting the old scissor rectangle over, nothing to do\n");
3341         return WINED3D_OK;
3342     }
3343     CopyRect(&This->updateStateBlock->scissorRect, pRect);
3344
3345     if(This->isRecordingState) {
3346         TRACE("Recording... not performing anything\n");
3347         return WINED3D_OK;
3348     }
3349
3350     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
3351
3352     return WINED3D_OK;
3353 }
3354
3355 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3356     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3357
3358     *pRect = This->updateStateBlock->scissorRect;
3359     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3360     return WINED3D_OK;
3361 }
3362
3363 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3364     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3365     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3366
3367     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3368
3369     This->updateStateBlock->vertexDecl = pDecl;
3370     This->updateStateBlock->changed.vertexDecl = TRUE;
3371
3372     if (This->isRecordingState) {
3373         TRACE("Recording... not performing anything\n");
3374         return WINED3D_OK;
3375     } else if(pDecl == oldDecl) {
3376         /* Checked after the assignment to allow proper stateblock recording */
3377         TRACE("Application is setting the old declaration over, nothing to do\n");
3378         return WINED3D_OK;
3379     }
3380
3381     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
3382     return WINED3D_OK;
3383 }
3384
3385 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3386     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3387
3388     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3389
3390     *ppDecl = This->stateBlock->vertexDecl;
3391     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3392     return WINED3D_OK;
3393 }
3394
3395 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3396     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3397     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3398
3399     This->updateStateBlock->vertexShader         = pShader;
3400     This->updateStateBlock->changed.vertexShader = TRUE;
3401
3402     if (This->isRecordingState) {
3403         if(pShader) IWineD3DVertexShader_AddRef(pShader);
3404         if(oldShader) IWineD3DVertexShader_Release(oldShader);
3405         TRACE("Recording... not performing anything\n");
3406         return WINED3D_OK;
3407     } else if(oldShader == pShader) {
3408         /* Checked here to allow proper stateblock recording */
3409         TRACE("App is setting the old shader over, nothing to do\n");
3410         return WINED3D_OK;
3411     }
3412
3413     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3414     if(pShader) IWineD3DVertexShader_AddRef(pShader);
3415     if(oldShader) IWineD3DVertexShader_Release(oldShader);
3416
3417     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
3418
3419     return WINED3D_OK;
3420 }
3421
3422 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3423     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3424
3425     if (NULL == ppShader) {
3426         return WINED3DERR_INVALIDCALL;
3427     }
3428     *ppShader = This->stateBlock->vertexShader;
3429     if( NULL != *ppShader)
3430         IWineD3DVertexShader_AddRef(*ppShader);
3431
3432     TRACE("(%p) : returning %p\n", This, *ppShader);
3433     return WINED3D_OK;
3434 }
3435
3436 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
3437     IWineD3DDevice *iface,
3438     UINT start,
3439     CONST BOOL *srcData,
3440     UINT count) {
3441
3442     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3443     int i, cnt = min(count, MAX_CONST_B - start);
3444
3445     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3446             iface, srcData, start, count);
3447
3448     if (srcData == NULL || cnt < 0)
3449         return WINED3DERR_INVALIDCALL;
3450
3451     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3452     for (i = 0; i < cnt; i++)
3453         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3454
3455     for (i = start; i < cnt + start; ++i) {
3456         This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
3457     }
3458
3459     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3460
3461     return WINED3D_OK;
3462 }
3463
3464 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
3465     IWineD3DDevice *iface,
3466     UINT start,
3467     BOOL *dstData,
3468     UINT count) {
3469
3470     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3471     int cnt = min(count, MAX_CONST_B - start);
3472
3473     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3474             iface, dstData, start, count);
3475
3476     if (dstData == NULL || cnt < 0)
3477         return WINED3DERR_INVALIDCALL;
3478
3479     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
3480     return WINED3D_OK;
3481 }
3482
3483 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
3484     IWineD3DDevice *iface,
3485     UINT start,
3486     CONST int *srcData,
3487     UINT count) {
3488
3489     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3490     int i, cnt = min(count, MAX_CONST_I - start);
3491
3492     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3493             iface, srcData, start, count);
3494
3495     if (srcData == NULL || cnt < 0)
3496         return WINED3DERR_INVALIDCALL;
3497
3498     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3499     for (i = 0; i < cnt; i++)
3500         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3501            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3502
3503     for (i = start; i < cnt + start; ++i) {
3504         This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
3505     }
3506
3507     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3508
3509     return WINED3D_OK;
3510 }
3511
3512 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
3513     IWineD3DDevice *iface,
3514     UINT start,
3515     int *dstData,
3516     UINT count) {
3517
3518     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3519     int cnt = min(count, MAX_CONST_I - start);
3520
3521     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3522             iface, dstData, start, count);
3523
3524     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
3525         return WINED3DERR_INVALIDCALL;
3526
3527     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3528     return WINED3D_OK;
3529 }
3530
3531 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3532     IWineD3DDevice *iface,
3533     UINT start,
3534     CONST float *srcData,
3535     UINT count) {
3536
3537     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3538     int i;
3539
3540     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3541             iface, srcData, start, count);
3542
3543     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3544     if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
3545         return WINED3DERR_INVALIDCALL;
3546
3547     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3548     if(TRACE_ON(d3d)) {
3549         for (i = 0; i < count; i++)
3550             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3551                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3552     }
3553
3554     for (i = start; i < count + start; ++i) {
3555         if (!This->updateStateBlock->changed.vertexShaderConstantsF[i]) {
3556             constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_vconstantsF), constants_entry, entry);
3557             if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
3558                 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
3559                 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
3560             }
3561             ptr->idx[ptr->count++] = i;
3562             This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
3563         }
3564     }
3565
3566     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3567
3568     return WINED3D_OK;
3569 }
3570
3571 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst(
3572 IWineD3DDevice *iface,
3573 UINT start,
3574 CONST float *srcData,
3575 UINT count) {
3576
3577     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3578     int i;
3579
3580     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3581             iface, srcData, start, count);
3582
3583     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3584     if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
3585         return WINED3DERR_INVALIDCALL;
3586
3587     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3588     if(TRACE_ON(d3d)) {
3589         for (i = 0; i < count; i++)
3590             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3591                     srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3592     }
3593
3594     /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
3595      * context. On a context switch the old context will be fully dirtified
3596      */
3597     memset(This->activeContext->vshader_const_dirty + start, 1,
3598            sizeof(*This->activeContext->vshader_const_dirty) * count);
3599     This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start+count);
3600
3601     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3602
3603     return WINED3D_OK;
3604 }
3605
3606 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3607     IWineD3DDevice *iface,
3608     UINT start,
3609     float *dstData,
3610     UINT count) {
3611
3612     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3613     int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3614
3615     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3616             iface, dstData, start, count);
3617
3618     if (dstData == NULL || cnt < 0)
3619         return WINED3DERR_INVALIDCALL;
3620
3621     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3622     return WINED3D_OK;
3623 }
3624
3625 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3626     DWORD i;
3627     for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
3628         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3629     }
3630 }
3631
3632 static void device_map_stage(IWineD3DDeviceImpl *This, int stage, int unit) {
3633     int i = This->rev_tex_unit_map[unit];
3634     int j = This->texUnitMap[stage];
3635
3636     This->texUnitMap[stage] = unit;
3637     if (i != -1 && i != stage) {
3638         This->texUnitMap[i] = -1;
3639     }
3640
3641     This->rev_tex_unit_map[unit] = stage;
3642     if (j != -1 && j != unit) {
3643         This->rev_tex_unit_map[j] = -1;
3644     }
3645 }
3646
3647 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) {
3648     int i;
3649
3650     for (i = 0; i < MAX_TEXTURES; ++i) {
3651         WINED3DTEXTUREOP color_op = This->stateBlock->textureState[i][WINED3DTSS_COLOROP];
3652         WINED3DTEXTUREOP alpha_op = This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP];
3653         DWORD color_arg1 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG1] & WINED3DTA_SELECTMASK;
3654         DWORD color_arg2 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG2] & WINED3DTA_SELECTMASK;
3655         DWORD color_arg3 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG0] & WINED3DTA_SELECTMASK;
3656         DWORD alpha_arg1 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1] & WINED3DTA_SELECTMASK;
3657         DWORD alpha_arg2 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2] & WINED3DTA_SELECTMASK;
3658         DWORD alpha_arg3 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0] & WINED3DTA_SELECTMASK;
3659
3660         if (color_op == WINED3DTOP_DISABLE) {
3661             /* Not used, and disable higher stages */
3662             while (i < MAX_TEXTURES) {
3663                 This->fixed_function_usage_map[i] = FALSE;
3664                 ++i;
3665             }
3666             break;
3667         }
3668
3669         if (((color_arg1 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG2)
3670                 || ((color_arg2 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG1)
3671                 || ((color_arg3 == WINED3DTA_TEXTURE) && (color_op == WINED3DTOP_MULTIPLYADD || color_op == WINED3DTOP_LERP))
3672                 || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG2)
3673                 || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG1)
3674                 || ((alpha_arg3 == WINED3DTA_TEXTURE) && (alpha_op == WINED3DTOP_MULTIPLYADD || alpha_op == WINED3DTOP_LERP))) {
3675             This->fixed_function_usage_map[i] = TRUE;
3676         } else {
3677             This->fixed_function_usage_map[i] = FALSE;
3678         }
3679
3680         if ((color_op == WINED3DTOP_BUMPENVMAP || color_op == WINED3DTOP_BUMPENVMAPLUMINANCE) && i < MAX_TEXTURES - 1) {
3681             This->fixed_function_usage_map[i+1] = TRUE;
3682         }
3683     }
3684 }
3685
3686 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) {
3687     int i, tex;
3688
3689     device_update_fixed_function_usage_map(This);
3690
3691     if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) {
3692         for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) {
3693             if (!This->fixed_function_usage_map[i]) continue;
3694
3695             if (This->texUnitMap[i] != i) {
3696                 device_map_stage(This, i, i);
3697                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3698                 markTextureStagesDirty(This, i);
3699             }
3700         }
3701         return;
3702     }
3703
3704     /* Now work out the mapping */
3705     tex = 0;
3706     for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) {
3707         if (!This->fixed_function_usage_map[i]) continue;
3708
3709         if (This->texUnitMap[i] != tex) {
3710             device_map_stage(This, i, tex);
3711             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3712             markTextureStagesDirty(This, i);
3713         }
3714
3715         ++tex;
3716     }
3717 }
3718
3719 static void device_map_psamplers(IWineD3DDeviceImpl *This) {
3720     DWORD *sampler_tokens = ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.reg_maps.samplers;
3721     int i;
3722
3723     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) {
3724         if (sampler_tokens[i] && This->texUnitMap[i] != i) {
3725             device_map_stage(This, i, i);
3726             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3727             if (i < MAX_TEXTURES) {
3728                 markTextureStagesDirty(This, i);
3729             }
3730         }
3731     }
3732 }
3733
3734 static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, DWORD *pshader_sampler_tokens, DWORD *vshader_sampler_tokens, int unit) {
3735     int current_mapping = This->rev_tex_unit_map[unit];
3736
3737     if (current_mapping == -1) {
3738         /* Not currently used */
3739         return TRUE;
3740     }
3741
3742     if (current_mapping < MAX_FRAGMENT_SAMPLERS) {
3743         /* Used by a fragment sampler */
3744
3745         if (!pshader_sampler_tokens) {
3746             /* No pixel shader, check fixed function */
3747             return current_mapping >= MAX_TEXTURES || !This->fixed_function_usage_map[current_mapping];
3748         }
3749
3750         /* Pixel shader, check the shader's sampler map */
3751         return !pshader_sampler_tokens[current_mapping];
3752     }
3753
3754     /* Used by a vertex sampler */
3755     return !vshader_sampler_tokens[current_mapping];
3756 }
3757
3758 static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) {
3759     DWORD *vshader_sampler_tokens = ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.reg_maps.samplers;
3760     DWORD *pshader_sampler_tokens = NULL;
3761     int start = GL_LIMITS(combined_samplers) - 1;
3762     int i;
3763
3764     if (ps) {
3765         IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader;
3766
3767         /* Make sure the shader's reg_maps are up to date. This is only relevant for 1.x pixelshaders. */
3768         IWineD3DPixelShader_CompileShader((IWineD3DPixelShader *)pshader);
3769         pshader_sampler_tokens = pshader->baseShader.reg_maps.samplers;
3770     }
3771
3772     for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
3773         int vsampler_idx = i + MAX_FRAGMENT_SAMPLERS;
3774         if (vshader_sampler_tokens[i]) {
3775             if (This->texUnitMap[vsampler_idx] != -1) {
3776                 /* Already mapped somewhere */
3777                 continue;
3778             }
3779
3780             while (start >= 0) {
3781                 if (device_unit_free_for_vs(This, pshader_sampler_tokens, vshader_sampler_tokens, start)) {
3782                     device_map_stage(This, vsampler_idx, start);
3783                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(vsampler_idx));
3784
3785                     --start;
3786                     break;
3787                 }
3788
3789                 --start;
3790             }
3791         }
3792     }
3793 }
3794
3795 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3796     BOOL vs = use_vs(This);
3797     BOOL ps = use_ps(This);
3798     /*
3799      * Rules are:
3800      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3801      * that would be really messy and require shader recompilation
3802      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3803      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3804      */
3805     if (ps) {
3806         device_map_psamplers(This);
3807     } else {
3808         device_map_fixed_function_samplers(This);
3809     }
3810
3811     if (vs) {
3812         device_map_vsamplers(This, ps);
3813     }
3814 }
3815
3816 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3817     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3818     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3819     This->updateStateBlock->pixelShader         = pShader;
3820     This->updateStateBlock->changed.pixelShader = TRUE;
3821
3822     /* Handle recording of state blocks */
3823     if (This->isRecordingState) {
3824         TRACE("Recording... not performing anything\n");
3825     }
3826
3827     if (This->isRecordingState) {
3828         TRACE("Recording... not performing anything\n");
3829         if(pShader) IWineD3DPixelShader_AddRef(pShader);
3830         if(oldShader) IWineD3DPixelShader_Release(oldShader);
3831         return WINED3D_OK;
3832     }
3833
3834     if(pShader == oldShader) {
3835         TRACE("App is setting the old pixel shader over, nothing to do\n");
3836         return WINED3D_OK;
3837     }
3838
3839     if(pShader) IWineD3DPixelShader_AddRef(pShader);
3840     if(oldShader) IWineD3DPixelShader_Release(oldShader);
3841
3842     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3843     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3844
3845     return WINED3D_OK;
3846 }
3847
3848 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3849     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3850
3851     if (NULL == ppShader) {
3852         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3853         return WINED3DERR_INVALIDCALL;
3854     }
3855
3856     *ppShader =  This->stateBlock->pixelShader;
3857     if (NULL != *ppShader) {
3858         IWineD3DPixelShader_AddRef(*ppShader);
3859     }
3860     TRACE("(%p) : returning %p\n", This, *ppShader);
3861     return WINED3D_OK;
3862 }
3863
3864 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3865     IWineD3DDevice *iface,
3866     UINT start,
3867     CONST BOOL *srcData,
3868     UINT count) {
3869
3870     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3871     int i, cnt = min(count, MAX_CONST_B - start);
3872
3873     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3874             iface, srcData, start, count);
3875
3876     if (srcData == NULL || cnt < 0)
3877         return WINED3DERR_INVALIDCALL;
3878
3879     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3880     for (i = 0; i < cnt; i++)
3881         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3882
3883     for (i = start; i < cnt + start; ++i) {
3884         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3885     }
3886
3887     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3888
3889     return WINED3D_OK;
3890 }
3891
3892 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3893     IWineD3DDevice *iface,
3894     UINT start,
3895     BOOL *dstData,
3896     UINT count) {
3897
3898     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3899     int cnt = min(count, MAX_CONST_B - start);
3900
3901     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3902             iface, dstData, start, count);
3903
3904     if (dstData == NULL || cnt < 0)
3905         return WINED3DERR_INVALIDCALL;
3906
3907     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3908     return WINED3D_OK;
3909 }
3910
3911 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3912     IWineD3DDevice *iface,
3913     UINT start,
3914     CONST int *srcData,
3915     UINT count) {
3916
3917     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3918     int i, cnt = min(count, MAX_CONST_I - start);
3919
3920     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3921             iface, srcData, start, count);
3922
3923     if (srcData == NULL || cnt < 0)
3924         return WINED3DERR_INVALIDCALL;
3925
3926     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3927     for (i = 0; i < cnt; i++)
3928         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3929            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3930
3931     for (i = start; i < cnt + start; ++i) {
3932         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3933     }
3934
3935     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3936
3937     return WINED3D_OK;
3938 }
3939
3940 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3941     IWineD3DDevice *iface,
3942     UINT start,
3943     int *dstData,
3944     UINT count) {
3945
3946     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3947     int cnt = min(count, MAX_CONST_I - start);
3948
3949     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3950             iface, dstData, start, count);
3951
3952     if (dstData == NULL || cnt < 0)
3953         return WINED3DERR_INVALIDCALL;
3954
3955     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3956     return WINED3D_OK;
3957 }
3958
3959 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3960     IWineD3DDevice *iface,
3961     UINT start,
3962     CONST float *srcData,
3963     UINT count) {
3964
3965     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3966     int i;
3967
3968     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3969             iface, srcData, start, count);
3970
3971     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3972     if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
3973         return WINED3DERR_INVALIDCALL;
3974
3975     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3976     if(TRACE_ON(d3d)) {
3977         for (i = 0; i < count; i++)
3978             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3979                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3980     }
3981
3982     for (i = start; i < count + start; ++i) {
3983         if (!This->updateStateBlock->changed.pixelShaderConstantsF[i]) {
3984             constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry);
3985             if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
3986                 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
3987                 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3988             }
3989             ptr->idx[ptr->count++] = i;
3990             This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3991         }
3992     }
3993
3994     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3995
3996     return WINED3D_OK;
3997 }
3998
3999 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst(
4000     IWineD3DDevice *iface,
4001     UINT start,
4002     CONST float *srcData,
4003     UINT count) {
4004
4005     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4006     int i;
4007
4008     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4009             iface, srcData, start, count);
4010
4011     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
4012     if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
4013         return WINED3DERR_INVALIDCALL;
4014
4015     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
4016     if(TRACE_ON(d3d)) {
4017         for (i = 0; i < count; i++)
4018             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
4019                     srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
4020     }
4021
4022     /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
4023      * context. On a context switch the old context will be fully dirtified
4024      */
4025     memset(This->activeContext->pshader_const_dirty + start, 1,
4026            sizeof(*This->activeContext->pshader_const_dirty) * count);
4027     This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start+count);
4028
4029     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
4030
4031     return WINED3D_OK;
4032 }
4033
4034 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
4035     IWineD3DDevice *iface,
4036     UINT start,
4037     float *dstData,
4038     UINT count) {
4039
4040     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4041     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
4042
4043     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4044             iface, dstData, start, count);
4045
4046     if (dstData == NULL || cnt < 0)
4047         return WINED3DERR_INVALIDCALL;
4048
4049     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
4050     return WINED3D_OK;
4051 }
4052
4053 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4054 static HRESULT
4055 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
4056     char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
4057     unsigned int i;
4058     DWORD DestFVF = dest->fvf;
4059     WINED3DVIEWPORT vp;
4060     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
4061     BOOL doClip;
4062     int numTextures;
4063
4064     if (lpStrideData->u.s.normal.lpData) {
4065         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4066     }
4067
4068     if (lpStrideData->u.s.position.lpData == NULL) {
4069         ERR("Source has no position mask\n");
4070         return WINED3DERR_INVALIDCALL;
4071     }
4072
4073     /* We might access VBOs from this code, so hold the lock */
4074     ENTER_GL();
4075
4076     if (dest->resource.allocatedMemory == NULL) {
4077         /* This may happen if we do direct locking into a vbo. Unlikely,
4078          * but theoretically possible(ddraw processvertices test)
4079          */
4080         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
4081         if(!dest->resource.allocatedMemory) {
4082             LEAVE_GL();
4083             ERR("Out of memory\n");
4084             return E_OUTOFMEMORY;
4085         }
4086         if(dest->vbo) {
4087             void *src;
4088             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
4089             checkGLcall("glBindBufferARB");
4090             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
4091             if(src) {
4092                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
4093             }
4094             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4095             checkGLcall("glUnmapBufferARB");
4096         }
4097     }
4098
4099     /* Get a pointer into the destination vbo(create one if none exists) and
4100      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
4101      */
4102     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
4103         dest->Flags |= VBFLAG_CREATEVBO;
4104         IWineD3DVertexBuffer_PreLoad((IWineD3DVertexBuffer *) dest);
4105     }
4106
4107     if(dest->vbo) {
4108         unsigned char extrabytes = 0;
4109         /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
4110          * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
4111          * this may write 4 extra bytes beyond the area that should be written
4112          */
4113         if(DestFVF == WINED3DFVF_XYZ) extrabytes = 4;
4114         dest_conv_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * get_flexible_vertex_size(DestFVF) + extrabytes);
4115         if(!dest_conv_addr) {
4116             ERR("Out of memory\n");
4117             /* Continue without storing converted vertices */
4118         }
4119         dest_conv = dest_conv_addr;
4120     }
4121
4122     /* Should I clip?
4123      * a) WINED3DRS_CLIPPING is enabled
4124      * b) WINED3DVOP_CLIP is passed
4125      */
4126     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
4127         static BOOL warned = FALSE;
4128         /*
4129          * The clipping code is not quite correct. Some things need
4130          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4131          * so disable clipping for now.
4132          * (The graphics in Half-Life are broken, and my processvertices
4133          *  test crashes with IDirect3DDevice3)
4134         doClip = TRUE;
4135          */
4136         doClip = FALSE;
4137         if(!warned) {
4138            warned = TRUE;
4139            FIXME("Clipping is broken and disabled for now\n");
4140         }
4141     } else doClip = FALSE;
4142     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
4143
4144     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4145                                  WINED3DTS_VIEW,
4146                                  &view_mat);
4147     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4148                                  WINED3DTS_PROJECTION,
4149                                  &proj_mat);
4150     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
4151                                  WINED3DTS_WORLDMATRIX(0),
4152                                  &world_mat);
4153
4154     TRACE("View mat:\n");
4155     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);
4156     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);
4157     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);
4158     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);
4159
4160     TRACE("Proj mat:\n");
4161     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);
4162     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);
4163     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);
4164     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);
4165
4166     TRACE("World mat:\n");
4167     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);
4168     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);
4169     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);
4170     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);
4171
4172     /* Get the viewport */
4173     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
4174     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
4175           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
4176
4177     multiply_matrix(&mat,&view_mat,&world_mat);
4178     multiply_matrix(&mat,&proj_mat,&mat);
4179
4180     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
4181
4182     for (i = 0; i < dwCount; i+= 1) {
4183         unsigned int tex_index;
4184
4185         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
4186              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
4187             /* The position first */
4188             float *p =
4189               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
4190             float x, y, z, rhw;
4191             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
4192
4193             /* Multiplication with world, view and projection matrix */
4194             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);
4195             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);
4196             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);
4197             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);
4198
4199             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
4200
4201             /* WARNING: The following things are taken from d3d7 and were not yet checked
4202              * against d3d8 or d3d9!
4203              */
4204
4205             /* Clipping conditions: From msdn
4206              *
4207              * A vertex is clipped if it does not match the following requirements
4208              * -rhw < x <= rhw
4209              * -rhw < y <= rhw
4210              *    0 < z <= rhw
4211              *    0 < rhw ( Not in d3d7, but tested in d3d7)
4212              *
4213              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4214              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4215              *
4216              */
4217
4218             if( !doClip ||
4219                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
4220                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
4221                   ( rhw > eps ) ) ) {
4222
4223                 /* "Normal" viewport transformation (not clipped)
4224                  * 1) The values are divided by rhw
4225                  * 2) The y axis is negative, so multiply it with -1
4226                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4227                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4228                  * 4) Multiply x with Width/2 and add Width/2
4229                  * 5) The same for the height
4230                  * 6) Add the viewpoint X and Y to the 2D coordinates and
4231                  *    The minimum Z value to z
4232                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4233                  *
4234                  * Well, basically it's simply a linear transformation into viewport
4235                  * coordinates
4236                  */
4237
4238                 x /= rhw;
4239                 y /= rhw;
4240                 z /= rhw;
4241
4242                 y *= -1;
4243
4244                 x *= vp.Width / 2;
4245                 y *= vp.Height / 2;
4246                 z *= vp.MaxZ - vp.MinZ;
4247
4248                 x += vp.Width / 2 + vp.X;
4249                 y += vp.Height / 2 + vp.Y;
4250                 z += vp.MinZ;
4251
4252                 rhw = 1 / rhw;
4253             } else {
4254                 /* That vertex got clipped
4255                  * Contrary to OpenGL it is not dropped completely, it just
4256                  * undergoes a different calculation.
4257                  */
4258                 TRACE("Vertex got clipped\n");
4259                 x += rhw;
4260                 y += rhw;
4261
4262                 x  /= 2;
4263                 y  /= 2;
4264
4265                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
4266                  * outside of the main vertex buffer memory. That needs some more
4267                  * investigation...
4268                  */
4269             }
4270
4271             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
4272
4273
4274             ( (float *) dest_ptr)[0] = x;
4275             ( (float *) dest_ptr)[1] = y;
4276             ( (float *) dest_ptr)[2] = z;
4277             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
4278
4279             dest_ptr += 3 * sizeof(float);
4280
4281             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4282                 dest_ptr += sizeof(float);
4283             }
4284
4285             if(dest_conv) {
4286                 float w = 1 / rhw;
4287                 ( (float *) dest_conv)[0] = x * w;
4288                 ( (float *) dest_conv)[1] = y * w;
4289                 ( (float *) dest_conv)[2] = z * w;
4290                 ( (float *) dest_conv)[3] = w;
4291
4292                 dest_conv += 3 * sizeof(float);
4293
4294                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
4295                     dest_conv += sizeof(float);
4296                 }
4297             }
4298         }
4299         if (DestFVF & WINED3DFVF_PSIZE) {
4300             dest_ptr += sizeof(DWORD);
4301             if(dest_conv) dest_conv += sizeof(DWORD);
4302         }
4303         if (DestFVF & WINED3DFVF_NORMAL) {
4304             float *normal =
4305               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
4306             /* AFAIK this should go into the lighting information */
4307             FIXME("Didn't expect the destination to have a normal\n");
4308             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
4309             if(dest_conv) {
4310                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
4311             }
4312         }
4313
4314         if (DestFVF & WINED3DFVF_DIFFUSE) {
4315             DWORD *color_d = 
4316               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
4317             if(!color_d) {
4318                 static BOOL warned = FALSE;
4319
4320                 if(!warned) {
4321                     ERR("No diffuse color in source, but destination has one\n");
4322                     warned = TRUE;
4323                 }
4324
4325                 *( (DWORD *) dest_ptr) = 0xffffffff;
4326                 dest_ptr += sizeof(DWORD);
4327
4328                 if(dest_conv) {
4329                     *( (DWORD *) dest_conv) = 0xffffffff;
4330                     dest_conv += sizeof(DWORD);
4331                 }
4332             }
4333             else {
4334                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
4335                 if(dest_conv) {
4336                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
4337                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
4338                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
4339                     dest_conv += sizeof(DWORD);
4340                 }
4341             }
4342         }
4343
4344         if (DestFVF & WINED3DFVF_SPECULAR) { 
4345             /* What's the color value in the feedback buffer? */
4346             DWORD *color_s = 
4347               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
4348             if(!color_s) {
4349                 static BOOL warned = FALSE;
4350
4351                 if(!warned) {
4352                     ERR("No specular color in source, but destination has one\n");
4353                     warned = TRUE;
4354                 }
4355
4356                 *( (DWORD *) dest_ptr) = 0xFF000000;
4357                 dest_ptr += sizeof(DWORD);
4358
4359                 if(dest_conv) {
4360                     *( (DWORD *) dest_conv) = 0xFF000000;
4361                     dest_conv += sizeof(DWORD);
4362                 }
4363             }
4364             else {
4365                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4366                 if(dest_conv) {
4367                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
4368                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
4369                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
4370                     dest_conv += sizeof(DWORD);
4371                 }
4372             }
4373         }
4374
4375         for (tex_index = 0; tex_index < numTextures; tex_index++) {
4376             float *tex_coord =
4377               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
4378                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
4379             if(!tex_coord) {
4380                 ERR("No source texture, but destination requests one\n");
4381                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4382                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4383             }
4384             else {
4385                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4386                 if(dest_conv) {
4387                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4388                 }
4389             }
4390         }
4391     }
4392
4393     if(dest_conv) {
4394         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
4395         checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
4396         GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
4397                                       dwCount * get_flexible_vertex_size(DestFVF),
4398                                       dest_conv_addr));
4399         checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
4400         HeapFree(GetProcessHeap(), 0, dest_conv_addr);
4401     }
4402
4403     LEAVE_GL();
4404
4405     return WINED3D_OK;
4406 }
4407 #undef copy_and_next
4408
4409 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexDeclaration* pVertexDecl, DWORD Flags) {
4410     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4411     WineDirect3DVertexStridedData strided;
4412     BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP;
4413     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4414
4415     if(pVertexDecl) {
4416         ERR("Output vertex declaration not implemented yet\n");
4417     }
4418
4419     /* Need any context to write to the vbo. */
4420     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4421
4422     /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
4423      * control the streamIsUP flag, thus restore it afterwards.
4424      */
4425     This->stateBlock->streamIsUP = FALSE;
4426     memset(&strided, 0, sizeof(strided));
4427     primitiveDeclarationConvertToStridedData(iface, FALSE, &strided, &vbo);
4428     This->stateBlock->streamIsUP = streamWasUP;
4429
4430     if(vbo || SrcStartIndex) {
4431         unsigned int i;
4432         /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
4433          * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the strided structure
4434          *
4435          * Also get the start index in, but only loop over all elements if there's something to add at all.
4436          */
4437 #define FIXSRC(type) \
4438         if(strided.u.s.type.VBO) { \
4439             IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[strided.u.s.type.streamNo]; \
4440             strided.u.s.type.VBO = 0; \
4441             strided.u.s.type.lpData = (BYTE *) ((unsigned long) strided.u.s.type.lpData + (unsigned long) vb->resource.allocatedMemory); \
4442             ENTER_GL(); \
4443             GL_EXTCALL(glDeleteBuffersARB(1, &vb->vbo)); \
4444             vb->vbo = 0; \
4445             LEAVE_GL(); \
4446         } \
4447         if(strided.u.s.type.lpData) { \
4448             strided.u.s.type.lpData += strided.u.s.type.dwStride * SrcStartIndex; \
4449         }
4450         FIXSRC(position);
4451         FIXSRC(blendWeights);
4452         FIXSRC(blendMatrixIndices);
4453         FIXSRC(normal);
4454         FIXSRC(pSize);
4455         FIXSRC(diffuse);
4456         FIXSRC(specular);
4457         for(i = 0; i < WINED3DDP_MAXTEXCOORD; i++) {
4458             FIXSRC(texCoords[i]);
4459         }
4460         FIXSRC(position2);
4461         FIXSRC(normal2);
4462         FIXSRC(tangent);
4463         FIXSRC(binormal);
4464         FIXSRC(tessFactor);
4465         FIXSRC(fog);
4466         FIXSRC(depth);
4467         FIXSRC(sample);
4468 #undef FIXSRC
4469     }
4470
4471     return process_vertices_strided(This, DestIndex, VertexCount, &strided, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4472 }
4473
4474 /*****
4475  * Get / Set Texture Stage States
4476  * TODO: Verify against dx9 definitions
4477  *****/
4478 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4479     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4480     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
4481
4482     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4483
4484     if (Stage >= MAX_TEXTURES) {
4485         WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring\n", Stage, MAX_TEXTURES - 1);
4486         return WINED3D_OK;
4487     }
4488
4489     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4490     This->updateStateBlock->textureState[Stage][Type]         = Value;
4491
4492     if (This->isRecordingState) {
4493         TRACE("Recording... not performing anything\n");
4494         return WINED3D_OK;
4495     }
4496
4497     /* Checked after the assignments to allow proper stateblock recording */
4498     if(oldValue == Value) {
4499         TRACE("App is setting the old value over, nothing to do\n");
4500         return WINED3D_OK;
4501     }
4502
4503     if(Stage > This->stateBlock->lowest_disabled_stage &&
4504        This->shader_backend->StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
4505         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4506          * Changes in other states are important on disabled stages too
4507          */
4508         return WINED3D_OK;
4509     }
4510
4511     if(Type == WINED3DTSS_COLOROP) {
4512         int i;
4513
4514         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
4515             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4516              * they have to be disabled
4517              *
4518              * The current stage is dirtified below.
4519              */
4520             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
4521                 TRACE("Additionally dirtifying stage %d\n", i);
4522                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4523             }
4524             This->stateBlock->lowest_disabled_stage = Stage;
4525             TRACE("New lowest disabled: %d\n", Stage);
4526         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
4527             /* Previously disabled stage enabled. Stages above it may need enabling
4528              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4529              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4530              *
4531              * Again stage Stage doesn't need to be dirtified here, it is handled below.
4532              */
4533
4534             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
4535                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
4536                     break;
4537                 }
4538                 TRACE("Additionally dirtifying stage %d due to enable\n", i);
4539                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4540             }
4541             This->stateBlock->lowest_disabled_stage = i;
4542             TRACE("New lowest disabled: %d\n", i);
4543         }
4544         if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4545             /* TODO: Built a stage -> texture unit mapping for register combiners */
4546         }
4547     }
4548
4549     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
4550
4551     return WINED3D_OK;
4552 }
4553
4554 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4555     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4556     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4557     *pValue = This->updateStateBlock->textureState[Stage][Type];
4558     return WINED3D_OK;
4559 }
4560
4561 /*****
4562  * Get / Set Texture
4563  *****/
4564 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4565     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4566     IWineD3DBaseTexture *oldTexture;
4567
4568     TRACE("(%p) : Stage %#x, Texture %p\n", This, Stage, pTexture);
4569
4570     if (Stage >= WINED3DVERTEXTEXTURESAMPLER0 && Stage <= WINED3DVERTEXTEXTURESAMPLER3) {
4571         Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4572     }
4573
4574     if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) {
4575         ERR("Current stage overflows textures array (stage %d)\n", Stage);
4576         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
4577     }
4578
4579     oldTexture = This->updateStateBlock->textures[Stage];
4580
4581     if(pTexture != NULL) {
4582         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
4583          */
4584         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
4585             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4586             return WINED3DERR_INVALIDCALL;
4587         }
4588         This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
4589     }
4590
4591     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
4592     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4593
4594     This->updateStateBlock->changed.textures[Stage] = TRUE;
4595     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4596     This->updateStateBlock->textures[Stage]         = pTexture;
4597
4598     /* Handle recording of state blocks */
4599     if (This->isRecordingState) {
4600         TRACE("Recording... not performing anything\n");
4601         return WINED3D_OK;
4602     }
4603
4604     if(oldTexture == pTexture) {
4605         TRACE("App is setting the same texture again, nothing to do\n");
4606         return WINED3D_OK;
4607     }
4608
4609     /** NOTE: MSDN says that setTexture increases the reference count,
4610     * and that the application must set the texture back to null (or have a leaky application),
4611     * This means we should pass the refcount up to the parent
4612      *******************************/
4613     if (NULL != This->updateStateBlock->textures[Stage]) {
4614         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
4615         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
4616
4617         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4618         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
4619             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4620              * so the COLOROP and ALPHAOP have to be dirtified.
4621              */
4622             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4623             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4624         }
4625         if(bindCount == 1) {
4626             new->baseTexture.sampler = Stage;
4627         }
4628         /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
4629
4630     }
4631
4632     if (NULL != oldTexture) {
4633         IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
4634         LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
4635
4636         IWineD3DBaseTexture_Release(oldTexture);
4637         if(pTexture == NULL && Stage < MAX_TEXTURES) {
4638             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4639             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4640         }
4641
4642         if(bindCount && old->baseTexture.sampler == Stage) {
4643             int i;
4644             /* Have to do a search for the other sampler(s) where the texture is bound to
4645              * Shouldn't happen as long as apps bind a texture only to one stage
4646              */
4647             TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
4648             for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
4649                 if(This->updateStateBlock->textures[i] == oldTexture) {
4650                     old->baseTexture.sampler = i;
4651                     break;
4652                 }
4653             }
4654         }
4655     }
4656
4657     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
4658
4659     return WINED3D_OK;
4660 }
4661
4662 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4663     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4664
4665     TRACE("(%p) : Stage %#x, ppTexture %p\n", This, Stage, ppTexture);
4666
4667     if (Stage >= WINED3DVERTEXTEXTURESAMPLER0 && Stage <= WINED3DVERTEXTEXTURESAMPLER3) {
4668         Stage -= (WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS);
4669     }
4670
4671     if (Stage >= sizeof(This->stateBlock->textures)/sizeof(This->stateBlock->textures[0])) {
4672         ERR("Current stage overflows textures array (stage %d)\n", Stage);
4673         return WINED3D_OK; /* Windows accepts overflowing this array ... we do not. */
4674     }
4675
4676     *ppTexture=This->stateBlock->textures[Stage];
4677     if (*ppTexture)
4678         IWineD3DBaseTexture_AddRef(*ppTexture);
4679
4680     TRACE("(%p) : Returning %p\n", This, *ppTexture);
4681
4682     return WINED3D_OK;
4683 }
4684
4685 /*****
4686  * Get Back Buffer
4687  *****/
4688 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4689                                                 IWineD3DSurface **ppBackBuffer) {
4690     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4691     IWineD3DSwapChain *swapChain;
4692     HRESULT hr;
4693
4694     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4695
4696     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4697     if (hr == WINED3D_OK) {
4698         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4699             IWineD3DSwapChain_Release(swapChain);
4700     } else {
4701         *ppBackBuffer = NULL;
4702     }
4703     return hr;
4704 }
4705
4706 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4707     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4708     WARN("(%p) : stub, calling idirect3d for now\n", This);
4709     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4710 }
4711
4712 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4713     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4714     IWineD3DSwapChain *swapChain;
4715     HRESULT hr;
4716
4717     if(iSwapChain > 0) {
4718         hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4719         if (hr == WINED3D_OK) {
4720             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4721             IWineD3DSwapChain_Release(swapChain);
4722         } else {
4723             FIXME("(%p) Error getting display mode\n", This);
4724         }
4725     } else {
4726         /* Don't read the real display mode,
4727            but return the stored mode instead. X11 can't change the color
4728            depth, and some apps are pretty angry if they SetDisplayMode from
4729            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4730
4731            Also don't relay to the swapchain because with ddraw it's possible
4732            that there isn't a swapchain at all */
4733         pMode->Width = This->ddraw_width;
4734         pMode->Height = This->ddraw_height;
4735         pMode->Format = This->ddraw_format;
4736         pMode->RefreshRate = 0;
4737         hr = WINED3D_OK;
4738     }
4739
4740     return hr;
4741 }
4742
4743 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4744     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4745     TRACE("(%p)->(%p)\n", This, hWnd);
4746
4747     if(This->ddraw_fullscreen) {
4748         if(This->ddraw_window && This->ddraw_window != hWnd) {
4749             IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
4750         }
4751         if(hWnd && This->ddraw_window != hWnd) {
4752             IWineD3DDeviceImpl_SetupFullscreenWindow(iface, hWnd);
4753         }
4754     }
4755
4756     This->ddraw_window = hWnd;
4757     return WINED3D_OK;
4758 }
4759
4760 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4761     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4762     TRACE("(%p)->(%p)\n", This, hWnd);
4763
4764     *hWnd = This->ddraw_window;
4765     return WINED3D_OK;
4766 }
4767
4768 /*****
4769  * Stateblock related functions
4770  *****/
4771
4772 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4773     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4774     IWineD3DStateBlockImpl *object;
4775     HRESULT temp_result;
4776     int i;
4777
4778     TRACE("(%p)\n", This);
4779     
4780     if (This->isRecordingState) {
4781         return WINED3DERR_INVALIDCALL;
4782     }
4783     
4784     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4785     if (NULL == object ) {
4786         FIXME("(%p)Error allocating memory for stateblock\n", This);
4787         return E_OUTOFMEMORY;
4788     }
4789     TRACE("(%p) created object %p\n", This, object);
4790     object->wineD3DDevice= This;
4791     /** FIXME: object->parent       = parent; **/
4792     object->parent       = NULL;
4793     object->blockType    = WINED3DSBT_RECORDED;
4794     object->ref          = 1;
4795     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4796
4797     for(i = 0; i < LIGHTMAP_SIZE; i++) {
4798         list_init(&object->lightMap[i]);
4799     }
4800
4801     temp_result = allocate_shader_constants(object);
4802     if (WINED3D_OK != temp_result)
4803         return temp_result;
4804
4805     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4806     This->updateStateBlock = object;
4807     This->isRecordingState = TRUE;
4808
4809     TRACE("(%p) recording stateblock %p\n",This , object);
4810     return WINED3D_OK;
4811 }
4812
4813 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4814     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4815     unsigned int i, j;
4816     IWineD3DStateBlockImpl *object = This->updateStateBlock;
4817
4818     if (!This->isRecordingState) {
4819         FIXME("(%p) not recording! returning error\n", This);
4820         *ppStateBlock = NULL;
4821         return WINED3DERR_INVALIDCALL;
4822     }
4823
4824     for(i = 1; i <= WINEHIGHEST_RENDER_STATE; i++) {
4825         if(object->changed.renderState[i]) {
4826             object->contained_render_states[object->num_contained_render_states] = i;
4827             object->num_contained_render_states++;
4828         }
4829     }
4830     for(i = 1; i <= HIGHEST_TRANSFORMSTATE; i++) {
4831         if(object->changed.transform[i]) {
4832             object->contained_transform_states[object->num_contained_transform_states] = i;
4833             object->num_contained_transform_states++;
4834         }
4835     }
4836     for(i = 0; i < GL_LIMITS(vshader_constantsF); i++) {
4837         if(object->changed.vertexShaderConstantsF[i]) {
4838             object->contained_vs_consts_f[object->num_contained_vs_consts_f] = i;
4839             object->num_contained_vs_consts_f++;
4840         }
4841     }
4842     for(i = 0; i < MAX_CONST_I; i++) {
4843         if(object->changed.vertexShaderConstantsI[i]) {
4844             object->contained_vs_consts_i[object->num_contained_vs_consts_i] = i;
4845             object->num_contained_vs_consts_i++;
4846         }
4847     }
4848     for(i = 0; i < MAX_CONST_B; i++) {
4849         if(object->changed.vertexShaderConstantsB[i]) {
4850             object->contained_vs_consts_b[object->num_contained_vs_consts_b] = i;
4851             object->num_contained_vs_consts_b++;
4852         }
4853     }
4854     for(i = 0; i < MAX_CONST_I; i++) {
4855         if(object->changed.pixelShaderConstantsI[i]) {
4856             object->contained_ps_consts_i[object->num_contained_ps_consts_i] = i;
4857             object->num_contained_ps_consts_i++;
4858         }
4859     }
4860     for(i = 0; i < MAX_CONST_B; i++) {
4861         if(object->changed.pixelShaderConstantsB[i]) {
4862             object->contained_ps_consts_b[object->num_contained_ps_consts_b] = i;
4863             object->num_contained_ps_consts_b++;
4864         }
4865     }
4866     for(i = 0; i < MAX_TEXTURES; i++) {
4867         for(j = 1; j <= WINED3D_HIGHEST_TEXTURE_STATE; j++) {
4868             if(object->changed.textureState[i][j]) {
4869                 object->contained_tss_states[object->num_contained_tss_states].stage = i;
4870                 object->contained_tss_states[object->num_contained_tss_states].state = j;
4871                 object->num_contained_tss_states++;
4872             }
4873         }
4874     }
4875     for(i = 0; i < MAX_COMBINED_SAMPLERS; i++){
4876         for (j = 1; j < WINED3D_HIGHEST_SAMPLER_STATE; j++) {
4877             if(object->changed.samplerState[i][j]) {
4878                 object->contained_sampler_states[object->num_contained_sampler_states].stage = i;
4879                 object->contained_sampler_states[object->num_contained_sampler_states].state = j;
4880                 object->num_contained_sampler_states++;
4881             }
4882         }
4883     }
4884
4885     *ppStateBlock = (IWineD3DStateBlock*) object;
4886     This->isRecordingState = FALSE;
4887     This->updateStateBlock = This->stateBlock;
4888     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4889     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4890     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4891     return WINED3D_OK;
4892 }
4893
4894 /*****
4895  * Scene related functions
4896  *****/
4897 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4898     /* At the moment we have no need for any functionality at the beginning
4899        of a scene                                                          */
4900     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4901     TRACE("(%p)\n", This);
4902
4903     if(This->inScene) {
4904         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4905         return WINED3DERR_INVALIDCALL;
4906     }
4907     This->inScene = TRUE;
4908     return WINED3D_OK;
4909 }
4910
4911 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4912     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4913     TRACE("(%p)\n", This);
4914
4915     if(!This->inScene) {
4916         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4917         return WINED3DERR_INVALIDCALL;
4918     }
4919
4920     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4921     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4922     ENTER_GL();
4923     glFlush();
4924     checkGLcall("glFlush");
4925     LEAVE_GL();
4926
4927     This->inScene = FALSE;
4928     return WINED3D_OK;
4929 }
4930
4931 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4932                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4933                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4934     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4935     IWineD3DSwapChain *swapChain = NULL;
4936     int i;
4937     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4938
4939     TRACE("(%p) Presenting the frame\n", This);
4940
4941     for(i = 0 ; i < swapchains ; i ++) {
4942
4943         IWineD3DDeviceImpl_GetSwapChain(iface, i, &swapChain);
4944         TRACE("presentinng chain %d, %p\n", i, swapChain);
4945         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4946         IWineD3DSwapChain_Release(swapChain);
4947     }
4948
4949     return WINED3D_OK;
4950 }
4951
4952 /* Not called from the VTable (internal subroutine) */
4953 HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This,  IWineD3DSurfaceImpl *target, DWORD Count,
4954                                         CONST WINED3DRECT* pRects, DWORD Flags, WINED3DCOLOR Color,
4955                                         float Z, DWORD Stencil) {
4956     GLbitfield     glMask = 0;
4957     unsigned int   i;
4958     WINED3DRECT curRect;
4959     RECT vp_rect;
4960     WINED3DVIEWPORT *vp = &This->stateBlock->viewport;
4961     UINT drawable_width, drawable_height;
4962     IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *) This->stencilBufferTarget;
4963
4964     /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
4965      * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
4966      * for the cleared parts, and the untouched parts.
4967      *
4968      * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
4969      * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
4970      * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
4971      * checking all this if the dest surface is in the drawable anyway.
4972      */
4973     if((Flags & WINED3DCLEAR_TARGET) && !(target->Flags & SFLAG_INDRAWABLE)) {
4974         while(1) {
4975             if(vp->X != 0 || vp->Y != 0 ||
4976                vp->Width < target->currentDesc.Width || vp->Height < target->currentDesc.Height) {
4977                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4978                 break;
4979             }
4980             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
4981                This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
4982                This->stateBlock->scissorRect.right < target->currentDesc.Width ||
4983                This->stateBlock->scissorRect.bottom < target->currentDesc.Height)) {
4984                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4985                 break;
4986             }
4987             if(Count > 0 && pRects && (
4988                pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
4989                pRects[0].x2 < target->currentDesc.Width ||
4990                pRects[0].y2 < target->currentDesc.Height)) {
4991                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4992                 break;
4993             }
4994             break;
4995         }
4996     }
4997
4998     target->get_drawable_size(target, &drawable_width, &drawable_height);
4999
5000     ActivateContext(This, (IWineD3DSurface *) target, CTXUSAGE_CLEAR);
5001     ENTER_GL();
5002
5003     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5004         apply_fbo_state((IWineD3DDevice *) This);
5005     }
5006
5007     /* Only set the values up once, as they are not changing */
5008     if (Flags & WINED3DCLEAR_STENCIL) {
5009         glClearStencil(Stencil);
5010         checkGLcall("glClearStencil");
5011         glMask = glMask | GL_STENCIL_BUFFER_BIT;
5012         glStencilMask(0xFFFFFFFF);
5013     }
5014
5015     if (Flags & WINED3DCLEAR_ZBUFFER) {
5016         glDepthMask(GL_TRUE);
5017         glClearDepth(Z);
5018         checkGLcall("glClearDepth");
5019         glMask = glMask | GL_DEPTH_BUFFER_BIT;
5020         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
5021
5022         if(This->depth_copy_state == WINED3D_DCS_COPY) {
5023             if(vp->X != 0 || vp->Y != 0 ||
5024                vp->Width < depth_stencil->currentDesc.Width || vp->Height < depth_stencil->currentDesc.Height) {
5025                 depth_copy((IWineD3DDevice *) This);
5026             }
5027             else if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
5028                This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
5029                This->stateBlock->scissorRect.right < depth_stencil->currentDesc.Width ||
5030                This->stateBlock->scissorRect.bottom < depth_stencil->currentDesc.Height)) {
5031                 depth_copy((IWineD3DDevice *) This);
5032             }
5033             else if(Count > 0 && pRects && (
5034                pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
5035                pRects[0].x2 < depth_stencil->currentDesc.Width ||
5036                pRects[0].y2 < depth_stencil->currentDesc.Height)) {
5037                 depth_copy((IWineD3DDevice *) This);
5038             }
5039         }
5040         This->depth_copy_state = WINED3D_DCS_INITIAL;
5041     }
5042
5043     if (Flags & WINED3DCLEAR_TARGET) {
5044         TRACE("Clearing screen with glClear to color %x\n", Color);
5045         glClearColor(D3DCOLOR_R(Color),
5046                      D3DCOLOR_G(Color),
5047                      D3DCOLOR_B(Color),
5048                      D3DCOLOR_A(Color));
5049         checkGLcall("glClearColor");
5050
5051         /* Clear ALL colors! */
5052         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5053         glMask = glMask | GL_COLOR_BUFFER_BIT;
5054     }
5055
5056     vp_rect.left = vp->X;
5057     vp_rect.top = vp->Y;
5058     vp_rect.right = vp->X + vp->Width;
5059     vp_rect.bottom = vp->Y + vp->Height;
5060     if (!(Count > 0 && pRects)) {
5061         if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
5062             IntersectRect(&vp_rect, &vp_rect, &This->stateBlock->scissorRect);
5063         }
5064         if(This->render_offscreen) {
5065             glScissor(vp_rect.left, vp_rect.top,
5066                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
5067         } else {
5068             glScissor(vp_rect.left, drawable_height - vp_rect.bottom,
5069                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
5070         }
5071         checkGLcall("glScissor");
5072         glClear(glMask);
5073         checkGLcall("glClear");
5074     } else {
5075         /* Now process each rect in turn */
5076         for (i = 0; i < Count; i++) {
5077             /* Note gl uses lower left, width/height */
5078             IntersectRect((RECT *) &curRect, &vp_rect, (RECT *) &pRects[i]);
5079             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
5080                 IntersectRect((RECT *) &curRect, (RECT *) &curRect, &This->stateBlock->scissorRect);
5081             }
5082             TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This,
5083                   pRects[i].x1, pRects[i].y1, pRects[i].x2, pRects[i].y2,
5084                   curRect.x1, (target->currentDesc.Height - curRect.y2),
5085                   curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5086
5087             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
5088              * The rectangle is not cleared, no error is returned, but further rectanlges are
5089              * still cleared if they are valid
5090              */
5091             if(curRect.x1 > curRect.x2 || curRect.y1 > curRect.y2) {
5092                 TRACE("Rectangle with negative dimensions, ignoring\n");
5093                 continue;
5094             }
5095
5096             if(This->render_offscreen) {
5097                 glScissor(curRect.x1, curRect.y1,
5098                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5099             } else {
5100                 glScissor(curRect.x1, drawable_height - curRect.y2,
5101                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
5102             }
5103             checkGLcall("glScissor");
5104
5105             glClear(glMask);
5106             checkGLcall("glClear");
5107         }
5108     }
5109
5110     /* Restore the old values (why..?) */
5111     if (Flags & WINED3DCLEAR_STENCIL) {
5112         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
5113     }
5114     if (Flags & WINED3DCLEAR_TARGET) {
5115         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
5116         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
5117                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
5118                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
5119                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
5120
5121         /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
5122          * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
5123          */
5124         IWineD3DSurface_ModifyLocation(This->lastActiveRenderTarget, SFLAG_INDRAWABLE, TRUE);
5125         /* TODO: Move the fbo logic into ModifyLocation() */
5126         if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5127             target->Flags |= SFLAG_INTEXTURE;
5128         }
5129     }
5130     LEAVE_GL();
5131
5132     return WINED3D_OK;
5133 }
5134
5135 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
5136                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
5137     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5138     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0];
5139
5140     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This,
5141           Count, pRects, Flags, Color, Z, Stencil);
5142
5143     if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
5144         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
5145         /* TODO: What about depth stencil buffers without stencil bits? */
5146         return WINED3DERR_INVALIDCALL;
5147     }
5148
5149     return IWineD3DDeviceImpl_ClearSurface(This, target, Count, pRects, Flags, Color, Z, Stencil);
5150 }
5151
5152 /*****
5153  * Drawing functions
5154  *****/
5155 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
5156                                                 UINT PrimitiveCount) {
5157
5158     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5159
5160     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
5161                                debug_d3dprimitivetype(PrimitiveType),
5162                                StartVertex, PrimitiveCount);
5163
5164     if(!This->stateBlock->vertexDecl) {
5165         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5166         return WINED3DERR_INVALIDCALL;
5167     }
5168
5169     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
5170     if(This->stateBlock->streamIsUP) {
5171         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5172         This->stateBlock->streamIsUP = FALSE;
5173     }
5174
5175     if(This->stateBlock->loadBaseVertexIndex != 0) {
5176         This->stateBlock->loadBaseVertexIndex = 0;
5177         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5178     }
5179     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
5180     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
5181                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
5182     return WINED3D_OK;
5183 }
5184
5185 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5186 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5187                                                            WINED3DPRIMITIVETYPE PrimitiveType,
5188                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
5189
5190     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
5191     UINT                 idxStride = 2;
5192     IWineD3DIndexBuffer *pIB;
5193     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
5194     GLuint vbo;
5195
5196     pIB = This->stateBlock->pIndexData;
5197     if (!pIB) {
5198         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
5199          * without an index buffer set. (The first time at least...)
5200          * D3D8 simply dies, but I doubt it can do much harm to return
5201          * D3DERR_INVALIDCALL there as well. */
5202         ERR("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
5203         return WINED3DERR_INVALIDCALL;
5204     }
5205
5206     if(!This->stateBlock->vertexDecl) {
5207         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5208         return WINED3DERR_INVALIDCALL;
5209     }
5210
5211     if(This->stateBlock->streamIsUP) {
5212         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5213         This->stateBlock->streamIsUP = FALSE;
5214     }
5215     vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
5216
5217     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
5218           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5219           minIndex, NumVertices, startIndex, primCount);
5220
5221     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5222     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5223         idxStride = 2;
5224     } else {
5225         idxStride = 4;
5226     }
5227
5228     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
5229         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
5230         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5231     }
5232
5233     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
5234                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5235
5236     return WINED3D_OK;
5237 }
5238
5239 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5240                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5241                                                     UINT VertexStreamZeroStride) {
5242     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5243     IWineD3DVertexBuffer *vb;
5244
5245     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5246              debug_d3dprimitivetype(PrimitiveType),
5247              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5248
5249     if(!This->stateBlock->vertexDecl) {
5250         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5251         return WINED3DERR_INVALIDCALL;
5252     }
5253
5254     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5255     vb = This->stateBlock->streamSource[0];
5256     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5257     if(vb) IWineD3DVertexBuffer_Release(vb);
5258     This->stateBlock->streamOffset[0] = 0;
5259     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5260     This->stateBlock->streamIsUP = TRUE;
5261     This->stateBlock->loadBaseVertexIndex = 0;
5262
5263     /* TODO: Only mark dirty if drawing from a different UP address */
5264     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5265
5266     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
5267                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5268
5269     /* MSDN specifies stream zero settings must be set to NULL */
5270     This->stateBlock->streamStride[0] = 0;
5271     This->stateBlock->streamSource[0] = NULL;
5272
5273     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
5274      * the new stream sources or use UP drawing again
5275      */
5276     return WINED3D_OK;
5277 }
5278
5279 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5280                                                              UINT MinVertexIndex, UINT NumVertices,
5281                                                              UINT PrimitiveCount, CONST void* pIndexData,
5282                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5283                                                              UINT VertexStreamZeroStride) {
5284     int                 idxStride;
5285     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5286     IWineD3DVertexBuffer *vb;
5287     IWineD3DIndexBuffer *ib;
5288
5289     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5290              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5291              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5292              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5293
5294     if(!This->stateBlock->vertexDecl) {
5295         WARN("(%p) : Called without a valid vertex declaration set\n", This);
5296         return WINED3DERR_INVALIDCALL;
5297     }
5298
5299     if (IndexDataFormat == WINED3DFMT_INDEX16) {
5300         idxStride = 2;
5301     } else {
5302         idxStride = 4;
5303     }
5304
5305     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5306     vb = This->stateBlock->streamSource[0];
5307     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5308     if(vb) IWineD3DVertexBuffer_Release(vb);
5309     This->stateBlock->streamIsUP = TRUE;
5310     This->stateBlock->streamOffset[0] = 0;
5311     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5312
5313     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
5314     This->stateBlock->baseVertexIndex = 0;
5315     This->stateBlock->loadBaseVertexIndex = 0;
5316     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
5317     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5318     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5319
5320     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5321
5322     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5323     This->stateBlock->streamSource[0] = NULL;
5324     This->stateBlock->streamStride[0] = 0;
5325     ib = This->stateBlock->pIndexData;
5326     if(ib) {
5327         IWineD3DIndexBuffer_Release(ib);
5328         This->stateBlock->pIndexData = NULL;
5329     }
5330     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
5331      * SetStreamSource to specify a vertex buffer
5332      */
5333
5334     return WINED3D_OK;
5335 }
5336
5337 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5338     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5339
5340     /* Mark the state dirty until we have nicer tracking
5341      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5342      * that value.
5343      */
5344     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5345     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5346     This->stateBlock->baseVertexIndex = 0;
5347     This->up_strided = DrawPrimStrideData;
5348     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
5349     This->up_strided = NULL;
5350     return WINED3D_OK;
5351 }
5352
5353 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData, UINT NumVertices, CONST void *pIndexData, WINED3DFORMAT IndexDataFormat) {
5354     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5355     DWORD idxSize = (IndexDataFormat == WINED3DFMT_INDEX32 ? 4 : 2);
5356
5357     /* Mark the state dirty until we have nicer tracking
5358      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5359      * that value.
5360      */
5361     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5362     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5363     This->stateBlock->streamIsUP = TRUE;
5364     This->stateBlock->baseVertexIndex = 0;
5365     This->up_strided = DrawPrimStrideData;
5366     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* startvertexidx */, 0 /* numindices */, 0 /* startidx */, idxSize, pIndexData, 0 /* minindex */);
5367     This->up_strided = NULL;
5368     return WINED3D_OK;
5369 }
5370
5371 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface, IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume) {
5372     /* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
5373      * not callable by the app directly no parameter validation checks are needed here.
5374      */
5375     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5376     WINED3DLOCKED_BOX src;
5377     WINED3DLOCKED_BOX dst;
5378     HRESULT hr;
5379     TRACE("(%p)->(%p, %p)\n", This, pSourceVolume, pDestinationVolume);
5380
5381     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
5382      * dirtification to improve loading performance.
5383      */
5384     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
5385     if(FAILED(hr)) return hr;
5386     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
5387     if(FAILED(hr)) {
5388     IWineD3DVolume_UnlockBox(pSourceVolume);
5389             return hr;
5390     }
5391
5392     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
5393
5394     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
5395     if(FAILED(hr)) {
5396         IWineD3DVolume_UnlockBox(pSourceVolume);
5397     } else {
5398         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
5399     }
5400     return hr;
5401 }
5402
5403 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5404 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
5405     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5406     HRESULT hr = WINED3D_OK;
5407     WINED3DRESOURCETYPE sourceType;
5408     WINED3DRESOURCETYPE destinationType;
5409     int i ,levels;
5410
5411     /* TODO: think about moving the code into IWineD3DBaseTexture  */
5412
5413     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5414
5415     /* verify that the source and destination textures aren't NULL */
5416     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5417         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5418              This, pSourceTexture, pDestinationTexture);
5419         hr = WINED3DERR_INVALIDCALL;
5420     }
5421
5422     if (pSourceTexture == pDestinationTexture) {
5423         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5424              This, pSourceTexture, pDestinationTexture);
5425         hr = WINED3DERR_INVALIDCALL;
5426     }
5427     /* Verify that the source and destination textures are the same type */
5428     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5429     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5430
5431     if (sourceType != destinationType) {
5432         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5433              This);
5434         hr = WINED3DERR_INVALIDCALL;
5435     }
5436
5437     /* check that both textures have the identical numbers of levels  */
5438     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5439         WARN("(%p) : source (%p) and destination (%p) textures must have identical numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5440         hr = WINED3DERR_INVALIDCALL;
5441     }
5442
5443     if (WINED3D_OK == hr) {
5444
5445         /* Make sure that the destination texture is loaded */
5446         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5447
5448         /* Update every surface level of the texture */
5449         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5450
5451         switch (sourceType) {
5452         case WINED3DRTYPE_TEXTURE:
5453             {
5454                 IWineD3DSurface *srcSurface;
5455                 IWineD3DSurface *destSurface;
5456
5457                 for (i = 0 ; i < levels ; ++i) {
5458                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
5459                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5460                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5461                     IWineD3DSurface_Release(srcSurface);
5462                     IWineD3DSurface_Release(destSurface);
5463                     if (WINED3D_OK != hr) {
5464                         WARN("(%p) : Call to update surface failed\n", This);
5465                         return hr;
5466                     }
5467                 }
5468             }
5469             break;
5470         case WINED3DRTYPE_CUBETEXTURE:
5471             {
5472                 IWineD3DSurface *srcSurface;
5473                 IWineD3DSurface *destSurface;
5474                 WINED3DCUBEMAP_FACES faceType;
5475
5476                 for (i = 0 ; i < levels ; ++i) {
5477                     /* Update each cube face */
5478                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5479                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
5480                         if (WINED3D_OK != hr) {
5481                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5482                         } else {
5483                             TRACE("Got srcSurface %p\n", srcSurface);
5484                         }
5485                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5486                         if (WINED3D_OK != hr) {
5487                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5488                         } else {
5489                             TRACE("Got desrSurface %p\n", destSurface);
5490                         }
5491                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5492                         IWineD3DSurface_Release(srcSurface);
5493                         IWineD3DSurface_Release(destSurface);
5494                         if (WINED3D_OK != hr) {
5495                             WARN("(%p) : Call to update surface failed\n", This);
5496                             return hr;
5497                         }
5498                     }
5499                 }
5500             }
5501             break;
5502
5503         case WINED3DRTYPE_VOLUMETEXTURE:
5504             {
5505                 IWineD3DVolume  *srcVolume  = NULL;
5506                 IWineD3DVolume  *destVolume = NULL;
5507
5508                 for (i = 0 ; i < levels ; ++i) {
5509                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5510                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5511                     hr =  IWineD3DDeviceImpl_UpdateVolume(iface, srcVolume, destVolume);
5512                     IWineD3DVolume_Release(srcVolume);
5513                     IWineD3DVolume_Release(destVolume);
5514                     if (WINED3D_OK != hr) {
5515                         WARN("(%p) : Call to update volume failed\n", This);
5516                         return hr;
5517                     }
5518                 }
5519             }
5520             break;
5521
5522         default:
5523             FIXME("(%p) : Unsupported source and destination type\n", This);
5524             hr = WINED3DERR_INVALIDCALL;
5525         }
5526     }
5527
5528     return hr;
5529 }
5530
5531 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5532     IWineD3DSwapChain *swapChain;
5533     HRESULT hr;
5534     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5535     if(hr == WINED3D_OK) {
5536         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5537                 IWineD3DSwapChain_Release(swapChain);
5538     }
5539     return hr;
5540 }
5541
5542 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5543     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5544     /* return a sensible default */
5545     *pNumPasses = 1;
5546     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5547     FIXME("(%p) : stub\n", This);
5548     return WINED3D_OK;
5549 }
5550
5551 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl *device)
5552 {
5553     int i;
5554
5555     for (i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
5556             IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl*)device->stateBlock->textures[i];
5557             if (texture && (texture->resource.format == WINED3DFMT_P8 || texture->resource.format == WINED3DFMT_A8P8)) {
5558                 IWineD3DDeviceImpl_MarkStateDirty(device, STATE_SAMPLER(i));
5559             }
5560         }
5561 }
5562
5563 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5564     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5565     int j;
5566     UINT NewSize;
5567     PALETTEENTRY **palettes;
5568
5569     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5570
5571     if (PaletteNumber >= MAX_PALETTES) {
5572         ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5573         return WINED3DERR_INVALIDCALL;
5574     }
5575
5576     if (PaletteNumber >= This->NumberOfPalettes) {
5577         NewSize = This->NumberOfPalettes;
5578         do {
5579            NewSize *= 2;
5580         } while(PaletteNumber >= NewSize);
5581         palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize);
5582         if (!palettes) {
5583             ERR("Out of memory!\n");
5584             return E_OUTOFMEMORY;
5585         }
5586         This->palettes = palettes;
5587         This->NumberOfPalettes = NewSize;
5588     }
5589
5590     if (!This->palettes[PaletteNumber]) {
5591         This->palettes[PaletteNumber] = HeapAlloc(GetProcessHeap(),  0, sizeof(PALETTEENTRY) * 256);
5592         if (!This->palettes[PaletteNumber]) {
5593             ERR("Out of memory!\n");
5594             return E_OUTOFMEMORY;
5595         }
5596     }
5597
5598     for (j = 0; j < 256; ++j) {
5599         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5600         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5601         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5602         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5603     }
5604     if (PaletteNumber == This->currentPalette) dirtify_p8_texture_samplers(This);
5605     TRACE("(%p) : returning\n", This);
5606     return WINED3D_OK;
5607 }
5608
5609 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5610     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5611     int j;
5612     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5613     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5614         /* What happens in such situation isn't documented; Native seems to silently abort
5615            on such conditions. Return Invalid Call. */
5616         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5617         return WINED3DERR_INVALIDCALL;
5618     }
5619     for (j = 0; j < 256; ++j) {
5620         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5621         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5622         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5623         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5624     }
5625     TRACE("(%p) : returning\n", This);
5626     return WINED3D_OK;
5627 }
5628
5629 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5630     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5631     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5632     /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5633        (tested with reference rasterizer). Return Invalid Call. */
5634     if (PaletteNumber >= This->NumberOfPalettes || !This->palettes[PaletteNumber]) {
5635         ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
5636         return WINED3DERR_INVALIDCALL;
5637     }
5638     /*TODO: stateblocks */
5639     if (This->currentPalette != PaletteNumber) {
5640         This->currentPalette = PaletteNumber;
5641         dirtify_p8_texture_samplers(This);
5642     }
5643     TRACE("(%p) : returning\n", This);
5644     return WINED3D_OK;
5645 }
5646
5647 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5648     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5649     if (PaletteNumber == NULL) {
5650         WARN("(%p) : returning Invalid Call\n", This);
5651         return WINED3DERR_INVALIDCALL;
5652     }
5653     /*TODO: stateblocks */
5654     *PaletteNumber = This->currentPalette;
5655     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5656     return WINED3D_OK;
5657 }
5658
5659 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5660     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5661     static BOOL showFixmes = TRUE;
5662     if (showFixmes) {
5663         FIXME("(%p) : stub\n", This);
5664         showFixmes = FALSE;
5665     }
5666
5667     This->softwareVertexProcessing = bSoftware;
5668     return WINED3D_OK;
5669 }
5670
5671
5672 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5673     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5674     static BOOL showFixmes = TRUE;
5675     if (showFixmes) {
5676         FIXME("(%p) : stub\n", This);
5677         showFixmes = FALSE;
5678     }
5679     return This->softwareVertexProcessing;
5680 }
5681
5682
5683 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5684     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5685     IWineD3DSwapChain *swapChain;
5686     HRESULT hr;
5687
5688     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5689
5690     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5691     if(hr == WINED3D_OK){
5692         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5693         IWineD3DSwapChain_Release(swapChain);
5694     }else{
5695         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5696     }
5697     return hr;
5698 }
5699
5700
5701 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5702     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5703     static BOOL showfixmes = TRUE;
5704     if(nSegments != 0.0f) {
5705         if( showfixmes) {
5706             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5707             showfixmes = FALSE;
5708         }
5709     }
5710     return WINED3D_OK;
5711 }
5712
5713 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5714     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5715     static BOOL showfixmes = TRUE;
5716     if( showfixmes) {
5717         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5718         showfixmes = FALSE;
5719     }
5720     return 0.0f;
5721 }
5722
5723 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5724     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5725     /** TODO: remove casts to IWineD3DSurfaceImpl
5726      *       NOTE: move code to surface to accomplish this
5727       ****************************************/
5728     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5729     int srcWidth, srcHeight;
5730     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5731     WINED3DFORMAT destFormat, srcFormat;
5732     UINT          destSize;
5733     int srcLeft, destLeft, destTop;
5734     WINED3DPOOL       srcPool, destPool;
5735     int offset    = 0;
5736     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5737     glDescriptor *glDescription = NULL;
5738     GLenum dummy;
5739     int bpp;
5740     CONVERT_TYPES convert = NO_CONVERSION;
5741
5742     WINED3DSURFACE_DESC  winedesc;
5743
5744     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5745     memset(&winedesc, 0, sizeof(winedesc));
5746     winedesc.Width  = &srcSurfaceWidth;
5747     winedesc.Height = &srcSurfaceHeight;
5748     winedesc.Pool   = &srcPool;
5749     winedesc.Format = &srcFormat;
5750
5751     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5752
5753     winedesc.Width  = &destSurfaceWidth;
5754     winedesc.Height = &destSurfaceHeight;
5755     winedesc.Pool   = &destPool;
5756     winedesc.Format = &destFormat;
5757     winedesc.Size   = &destSize;
5758
5759     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5760
5761     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5762         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5763         return WINED3DERR_INVALIDCALL;
5764     }
5765
5766     /* This call loads the opengl surface directly, instead of copying the surface to the
5767      * destination's sysmem copy. If surface conversion is needed, use BltFast instead to
5768      * copy in sysmem and use regular surface loading.
5769      */
5770     d3dfmt_get_conv((IWineD3DSurfaceImpl *) pDestinationSurface, FALSE, TRUE,
5771                     &dummy, &dummy, &dummy, &convert, &bpp, FALSE);
5772     if(convert != NO_CONVERSION) {
5773         return IWineD3DSurface_BltFast(pDestinationSurface,
5774                                         pDestPoint  ? pDestPoint->x : 0,
5775                                         pDestPoint  ? pDestPoint->y : 0,
5776                                         pSourceSurface, (RECT *) pSourceRect, 0);
5777     }
5778
5779     if (destFormat == WINED3DFMT_UNKNOWN) {
5780         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5781         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5782
5783         /* Get the update surface description */
5784         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5785     }
5786
5787     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5788
5789     ENTER_GL();
5790
5791     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
5792         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5793         checkGLcall("glActiveTextureARB");
5794     }
5795
5796     /* Make sure the surface is loaded and up to date */
5797     IWineD3DSurface_PreLoad(pDestinationSurface);
5798
5799     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5800
5801     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5802     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5803     srcHeight  = pSourceRect ? pSourceRect->bottom - pSourceRect->top   : srcSurfaceHeight;
5804     srcLeft    = pSourceRect ? pSourceRect->left : 0;
5805     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5806     destTop    = pDestPoint  ? pDestPoint->y : 0;
5807
5808
5809     /* This function doesn't support compressed textures
5810     the pitch is just bytesPerPixel * width */
5811     if(srcWidth != srcSurfaceWidth  || srcLeft ){
5812         rowoffset = srcSurfaceWidth * pSrcSurface->bytesPerPixel;
5813         offset   += srcLeft * pSrcSurface->bytesPerPixel;
5814         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5815     }
5816     /* TODO DXT formats */
5817
5818     if(pSourceRect != NULL && pSourceRect->top != 0){
5819        offset +=  pSourceRect->top * srcSurfaceWidth * pSrcSurface->bytesPerPixel;
5820     }
5821     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5822     ,This
5823     ,glDescription->level
5824     ,destLeft
5825     ,destTop
5826     ,srcWidth
5827     ,srcHeight
5828     ,glDescription->glFormat
5829     ,glDescription->glType
5830     ,IWineD3DSurface_GetData(pSourceSurface)
5831     );
5832
5833     /* Sanity check */
5834     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5835
5836         /* need to lock the surface to get the data */
5837         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5838     }
5839
5840     /* TODO: Cube and volume support */
5841     if(rowoffset != 0){
5842         /* not a whole row so we have to do it a line at a time */
5843         int j;
5844
5845         /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */
5846         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5847
5848         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5849
5850                 glTexSubImage2D(glDescription->target
5851                     ,glDescription->level
5852                     ,destLeft
5853                     ,j
5854                     ,srcWidth
5855                     ,1
5856                     ,glDescription->glFormat
5857                     ,glDescription->glType
5858                     ,data /* could be quicker using */
5859                 );
5860             data += rowoffset;
5861         }
5862
5863     } else { /* Full width, so just write out the whole texture */
5864
5865         if (WINED3DFMT_DXT1 == destFormat ||
5866             WINED3DFMT_DXT2 == destFormat ||
5867             WINED3DFMT_DXT3 == destFormat ||
5868             WINED3DFMT_DXT4 == destFormat ||
5869             WINED3DFMT_DXT5 == destFormat) {
5870             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5871                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5872                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5873                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5874                 } if (destFormat != srcFormat) {
5875                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5876                 } else {
5877                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5878                                                         glDescription->level,
5879                                                         glDescription->glFormatInternal,
5880                                                         srcWidth,
5881                                                         srcHeight,
5882                                                         0,
5883                                                         destSize,
5884                                                         IWineD3DSurface_GetData(pSourceSurface));
5885                 }
5886             } else {
5887                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5888             }
5889
5890
5891         } else {
5892             glTexSubImage2D(glDescription->target
5893                     ,glDescription->level
5894                     ,destLeft
5895                     ,destTop
5896                     ,srcWidth
5897                     ,srcHeight
5898                     ,glDescription->glFormat
5899                     ,glDescription->glType
5900                     ,IWineD3DSurface_GetData(pSourceSurface)
5901                 );
5902         }
5903      }
5904     checkGLcall("glTexSubImage2D");
5905
5906     LEAVE_GL();
5907
5908     IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE);
5909     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
5910
5911     return WINED3D_OK;
5912 }
5913
5914 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5915     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5916     struct WineD3DRectPatch *patch;
5917     unsigned int i;
5918     struct list *e;
5919     BOOL found;
5920     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5921
5922     if(!(Handle || pRectPatchInfo)) {
5923         /* TODO: Write a test for the return value, thus the FIXME */
5924         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5925         return WINED3DERR_INVALIDCALL;
5926     }
5927
5928     if(Handle) {
5929         i = PATCHMAP_HASHFUNC(Handle);
5930         found = FALSE;
5931         LIST_FOR_EACH(e, &This->patches[i]) {
5932             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5933             if(patch->Handle == Handle) {
5934                 found = TRUE;
5935                 break;
5936             }
5937         }
5938
5939         if(!found) {
5940             TRACE("Patch does not exist. Creating a new one\n");
5941             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5942             patch->Handle = Handle;
5943             list_add_head(&This->patches[i], &patch->entry);
5944         } else {
5945             TRACE("Found existing patch %p\n", patch);
5946         }
5947     } else {
5948         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5949          * attributes we have to tesselate, read back, and draw. This needs a patch
5950          * management structure instance. Create one.
5951          *
5952          * A possible improvement is to check if a vertex shader is used, and if not directly
5953          * draw the patch.
5954          */
5955         FIXME("Drawing an uncached patch. This is slow\n");
5956         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5957     }
5958
5959     if(pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1] ||
5960        pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3] ||
5961        (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo)) != 0) ) {
5962         HRESULT hr;
5963         TRACE("Tesselation density or patch info changed, retesselating\n");
5964
5965         if(pRectPatchInfo) {
5966             patch->RectPatchInfo = *pRectPatchInfo;
5967         }
5968         patch->numSegs[0] = pNumSegs[0];
5969         patch->numSegs[1] = pNumSegs[1];
5970         patch->numSegs[2] = pNumSegs[2];
5971         patch->numSegs[3] = pNumSegs[3];
5972
5973         hr = tesselate_rectpatch(This, patch);
5974         if(FAILED(hr)) {
5975             WARN("Patch tesselation failed\n");
5976
5977             /* Do not release the handle to store the params of the patch */
5978             if(!Handle) {
5979                 HeapFree(GetProcessHeap(), 0, patch);
5980             }
5981             return hr;
5982         }
5983     }
5984
5985     This->currentPatch = patch;
5986     IWineD3DDevice_DrawPrimitiveStrided(iface, WINED3DPT_TRIANGLELIST, patch->numSegs[0] * patch->numSegs[1] * 2, &patch->strided);
5987     This->currentPatch = NULL;
5988
5989     /* Destroy uncached patches */
5990     if(!Handle) {
5991         HeapFree(GetProcessHeap(), 0, patch->mem);
5992         HeapFree(GetProcessHeap(), 0, patch);
5993     }
5994     return WINED3D_OK;
5995 }
5996
5997 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5998     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5999     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
6000     FIXME("(%p) : Stub\n", This);
6001     return WINED3D_OK;
6002 }
6003
6004 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
6005     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6006     int i;
6007     struct WineD3DRectPatch *patch;
6008     struct list *e;
6009     TRACE("(%p) Handle(%d)\n", This, Handle);
6010
6011     i = PATCHMAP_HASHFUNC(Handle);
6012     LIST_FOR_EACH(e, &This->patches[i]) {
6013         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
6014         if(patch->Handle == Handle) {
6015             TRACE("Deleting patch %p\n", patch);
6016             list_remove(&patch->entry);
6017             HeapFree(GetProcessHeap(), 0, patch->mem);
6018             HeapFree(GetProcessHeap(), 0, patch);
6019             return WINED3D_OK;
6020         }
6021     }
6022
6023     /* TODO: Write a test for the return value */
6024     FIXME("Attempt to destroy nonexistent patch\n");
6025     return WINED3DERR_INVALIDCALL;
6026 }
6027
6028 static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) {
6029     HRESULT hr;
6030     IWineD3DSwapChain *swapchain;
6031
6032     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain);
6033     if (SUCCEEDED(hr)) {
6034         IWineD3DSwapChain_Release((IUnknown *)swapchain);
6035         return swapchain;
6036     }
6037
6038     return NULL;
6039 }
6040
6041 static void bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) {
6042     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6043
6044     if (!*fbo) {
6045         GL_EXTCALL(glGenFramebuffersEXT(1, fbo));
6046         checkGLcall("glGenFramebuffersEXT()");
6047     }
6048     GL_EXTCALL(glBindFramebufferEXT(target, *fbo));
6049     checkGLcall("glBindFramebuffer()");
6050 }
6051
6052 /* TODO: Handle stencil attachments */
6053 static void attach_depth_stencil_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, IWineD3DSurface *depth_stencil, BOOL use_render_buffer) {
6054     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
6055
6056     if (use_render_buffer && depth_stencil_impl->current_renderbuffer) {
6057         GL_EXTCALL(glFramebufferRenderbufferEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id));
6058         checkGLcall("glFramebufferRenderbufferEXT()");
6059     } else {
6060         IWineD3DBaseTextureImpl *texture_impl;
6061         GLenum texttarget, target;
6062         GLint old_binding = 0;
6063
6064         texttarget = depth_stencil_impl->glDescription.target;
6065         if(texttarget == GL_TEXTURE_2D) {
6066             target = GL_TEXTURE_2D;
6067             glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
6068         } else if(texttarget == GL_TEXTURE_RECTANGLE_ARB) {
6069             target = GL_TEXTURE_RECTANGLE_ARB;
6070             glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
6071         } else {
6072             target = GL_TEXTURE_CUBE_MAP_ARB;
6073             glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
6074         }
6075
6076         IWineD3DSurface_PreLoad(depth_stencil);
6077
6078         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6079         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6080         glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
6081         glBindTexture(target, old_binding);
6082
6083         /* Update base texture states array */
6084         if (SUCCEEDED(IWineD3DSurface_GetContainer(depth_stencil, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
6085             texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
6086             texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
6087             if (texture_impl->baseTexture.bindCount) {
6088                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
6089             }
6090
6091             IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
6092         }
6093
6094         GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_DEPTH_ATTACHMENT_EXT, texttarget,
6095                     depth_stencil_impl->glDescription.textureName, depth_stencil_impl->glDescription.level));
6096         checkGLcall("glFramebufferTexture2DEXT()");
6097     }
6098 }
6099
6100 static void attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) {
6101     const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface;
6102     IWineD3DBaseTextureImpl *texture_impl;
6103     GLenum texttarget, target;
6104     GLint old_binding;
6105
6106     texttarget = surface_impl->glDescription.target;
6107     if(texttarget == GL_TEXTURE_2D) {
6108         target = GL_TEXTURE_2D;
6109         glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
6110     } else if(texttarget == GL_TEXTURE_RECTANGLE_ARB) {
6111         target = GL_TEXTURE_RECTANGLE_ARB;
6112         glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
6113     } else {
6114         target = GL_TEXTURE_CUBE_MAP_ARB;
6115         glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
6116     }
6117
6118     IWineD3DSurface_PreLoad(surface);
6119
6120     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6121     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6122     glBindTexture(target, old_binding);
6123
6124     /* Update base texture states array */
6125     if (SUCCEEDED(IWineD3DSurface_GetContainer(surface, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
6126         texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
6127         texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
6128         if (texture_impl->baseTexture.bindCount) {
6129             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
6130         }
6131
6132         IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
6133     }
6134
6135     GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget,
6136             surface_impl->glDescription.textureName, surface_impl->glDescription.level));
6137
6138     checkGLcall("attach_surface_fbo");
6139 }
6140
6141 static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONST WINED3DRECT *rect, WINED3DCOLOR color) {
6142     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6143     IWineD3DSwapChain *swapchain;
6144
6145     swapchain = get_swapchain(surface);
6146     if (swapchain) {
6147         GLenum buffer;
6148
6149         TRACE("Surface %p is onscreen\n", surface);
6150
6151         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6152         buffer = surface_get_gl_buffer(surface, swapchain);
6153         glDrawBuffer(buffer);
6154         checkGLcall("glDrawBuffer()");
6155     } else {
6156         TRACE("Surface %p is offscreen\n", surface);
6157         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->dst_fbo);
6158         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface);
6159         GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
6160         checkGLcall("glFramebufferRenderbufferEXT");
6161     }
6162
6163     if (rect) {
6164         glEnable(GL_SCISSOR_TEST);
6165         if(!swapchain) {
6166             glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1);
6167         } else {
6168             glScissor(rect->x1, ((IWineD3DSurfaceImpl *)surface)->currentDesc.Height - rect->y2,
6169                     rect->x2 - rect->x1, rect->y2 - rect->y1);
6170         }
6171         checkGLcall("glScissor");
6172     } else {
6173         glDisable(GL_SCISSOR_TEST);
6174     }
6175     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6176
6177     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6178     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
6179
6180     glClearColor(D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color));
6181     glClear(GL_COLOR_BUFFER_BIT);
6182     checkGLcall("glClear");
6183
6184     if (This->render_offscreen) {
6185         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6186     } else {
6187         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6188         checkGLcall("glBindFramebuffer()");
6189     }
6190
6191     if (swapchain && surface == ((IWineD3DSwapChainImpl *)swapchain)->frontBuffer
6192             && ((IWineD3DSwapChainImpl *)swapchain)->backBuffer) {
6193         glDrawBuffer(GL_BACK);
6194         checkGLcall("glDrawBuffer()");
6195     }
6196 }
6197
6198 static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) {
6199     unsigned int r, g, b, a;
6200     DWORD ret;
6201
6202     if(destfmt == WINED3DFMT_A8R8G8B8 || destfmt == WINED3DFMT_X8R8G8B8 ||
6203        destfmt == WINED3DFMT_R8G8B8)
6204         return color;
6205
6206     TRACE("Converting color %08x to format %s\n", color, debug_d3dformat(destfmt));
6207
6208     a = (color & 0xff000000) >> 24;
6209     r = (color & 0x00ff0000) >> 16;
6210     g = (color & 0x0000ff00) >>  8;
6211     b = (color & 0x000000ff) >>  0;
6212
6213     switch(destfmt)
6214     {
6215         case WINED3DFMT_R5G6B5:
6216             if(r == 0xff && g == 0xff && b == 0xff) return 0xffff;
6217             r = (r * 32) / 256;
6218             g = (g * 64) / 256;
6219             b = (b * 32) / 256;
6220             ret  = r << 11;
6221             ret |= g << 5;
6222             ret |= b;
6223             TRACE("Returning %08x\n", ret);
6224             return ret;
6225
6226         case WINED3DFMT_X1R5G5B5:
6227         case WINED3DFMT_A1R5G5B5:
6228             a = (a *  2) / 256;
6229             r = (r * 32) / 256;
6230             g = (g * 32) / 256;
6231             b = (b * 32) / 256;
6232             ret  = a << 15;
6233             ret |= r << 10;
6234             ret |= g <<  5;
6235             ret |= b <<  0;
6236             TRACE("Returning %08x\n", ret);
6237             return ret;
6238
6239         case WINED3DFMT_A8:
6240             TRACE("Returning %08x\n", a);
6241             return a;
6242
6243         case WINED3DFMT_X4R4G4B4:
6244         case WINED3DFMT_A4R4G4B4:
6245             a = (a * 16) / 256;
6246             r = (r * 16) / 256;
6247             g = (g * 16) / 256;
6248             b = (b * 16) / 256;
6249             ret  = a << 12;
6250             ret |= r <<  8;
6251             ret |= g <<  4;
6252             ret |= b <<  0;
6253             TRACE("Returning %08x\n", ret);
6254             return ret;
6255
6256         case WINED3DFMT_R3G3B2:
6257             r = (r * 8) / 256;
6258             g = (g * 8) / 256;
6259             b = (b * 4) / 256;
6260             ret  = r <<  5;
6261             ret |= g <<  2;
6262             ret |= b <<  0;
6263             TRACE("Returning %08x\n", ret);
6264             return ret;
6265
6266         case WINED3DFMT_X8B8G8R8:
6267         case WINED3DFMT_A8B8G8R8:
6268             ret  = a << 24;
6269             ret |= b << 16;
6270             ret |= g <<  8;
6271             ret |= r <<  0;
6272             TRACE("Returning %08x\n", ret);
6273             return ret;
6274
6275         case WINED3DFMT_A2R10G10B10:
6276             a = (a *    4) / 256;
6277             r = (r * 1024) / 256;
6278             g = (g * 1024) / 256;
6279             b = (b * 1024) / 256;
6280             ret  = a << 30;
6281             ret |= r << 20;
6282             ret |= g << 10;
6283             ret |= b <<  0;
6284             TRACE("Returning %08x\n", ret);
6285             return ret;
6286
6287         case WINED3DFMT_A2B10G10R10:
6288             a = (a *    4) / 256;
6289             r = (r * 1024) / 256;
6290             g = (g * 1024) / 256;
6291             b = (b * 1024) / 256;
6292             ret  = a << 30;
6293             ret |= b << 20;
6294             ret |= g << 10;
6295             ret |= r <<  0;
6296             TRACE("Returning %08x\n", ret);
6297             return ret;
6298
6299         default:
6300             FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt));
6301             return 0;
6302     }
6303 }
6304
6305 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
6306     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6307     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6308     WINEDDBLTFX BltFx;
6309     TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This, pSurface, pRect, color);
6310
6311     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6312         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6313         return WINED3DERR_INVALIDCALL;
6314     }
6315
6316     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
6317         ENTER_GL();
6318         color_fill_fbo(iface, pSurface, pRect, color);
6319         LEAVE_GL();
6320         return WINED3D_OK;
6321     } else {
6322         /* Just forward this to the DirectDraw blitting engine */
6323         memset(&BltFx, 0, sizeof(BltFx));
6324         BltFx.dwSize = sizeof(BltFx);
6325         BltFx.u5.dwFillColor = argb_to_fmt(color, surface->resource.format);
6326         return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE);
6327     }
6328 }
6329
6330 /* rendertarget and depth stencil functions */
6331 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6332     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6333
6334     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6335         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
6336         return WINED3DERR_INVALIDCALL;
6337     }
6338
6339     *ppRenderTarget = This->render_targets[RenderTargetIndex];
6340     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6341     /* Note inc ref on returned surface */
6342     if(*ppRenderTarget != NULL)
6343         IWineD3DSurface_AddRef(*ppRenderTarget);
6344     return WINED3D_OK;
6345 }
6346
6347 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6348     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6349     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6350     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6351     IWineD3DSwapChainImpl *Swapchain;
6352     HRESULT hr;
6353
6354     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6355
6356     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6357     if(hr != WINED3D_OK) {
6358         ERR("Can't get the swapchain\n");
6359         return hr;
6360     }
6361
6362     /* Make sure to release the swapchain */
6363     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6364
6365     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6366         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6367         return WINED3DERR_INVALIDCALL;
6368     }
6369     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6370         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6371         return WINED3DERR_INVALIDCALL;
6372     }
6373
6374     if(Swapchain->frontBuffer != Front) {
6375         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6376
6377         if(Swapchain->frontBuffer)
6378             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6379         Swapchain->frontBuffer = Front;
6380
6381         if(Swapchain->frontBuffer) {
6382             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6383         }
6384     }
6385
6386     if(Back && !Swapchain->backBuffer) {
6387         /* We need memory for the back buffer array - only one back buffer this way */
6388         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6389         if(!Swapchain->backBuffer) {
6390             ERR("Out of memory\n");
6391             return E_OUTOFMEMORY;
6392         }
6393     }
6394
6395     if(Swapchain->backBuffer[0] != Back) {
6396         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6397
6398         /* What to do about the context here in the case of multithreading? Not sure.
6399          * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
6400          */
6401         ENTER_GL();
6402         if(!Swapchain->backBuffer[0]) {
6403             /* GL was told to draw to the front buffer at creation,
6404              * undo that
6405              */
6406             glDrawBuffer(GL_BACK);
6407             checkGLcall("glDrawBuffer(GL_BACK)");
6408             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6409             Swapchain->presentParms.BackBufferCount = 1;
6410         } else if (!Back) {
6411             /* That makes problems - disable for now */
6412             /* glDrawBuffer(GL_FRONT); */
6413             checkGLcall("glDrawBuffer(GL_FRONT)");
6414             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6415             Swapchain->presentParms.BackBufferCount = 0;
6416         }
6417         LEAVE_GL();
6418
6419         if(Swapchain->backBuffer[0])
6420             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6421         Swapchain->backBuffer[0] = Back;
6422
6423         if(Swapchain->backBuffer[0]) {
6424             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6425         } else {
6426             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6427             Swapchain->backBuffer = NULL;
6428         }
6429
6430     }
6431
6432     return WINED3D_OK;
6433 }
6434
6435 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6436     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6437     *ppZStencilSurface = This->stencilBufferTarget;
6438     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
6439
6440     if(*ppZStencilSurface != NULL) {
6441         /* Note inc ref on returned surface */
6442         IWineD3DSurface_AddRef(*ppZStencilSurface);
6443         return WINED3D_OK;
6444     } else {
6445         return WINED3DERR_NOTFOUND;
6446     }
6447 }
6448
6449 /* TODO: Handle stencil attachments */
6450 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
6451     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6452
6453     TRACE("Set depth stencil to %p\n", depth_stencil);
6454
6455     if (depth_stencil) {
6456         attach_depth_stencil_fbo(This, GL_FRAMEBUFFER_EXT, depth_stencil, TRUE);
6457     } else {
6458         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
6459         checkGLcall("glFramebufferTexture2DEXT()");
6460     }
6461 }
6462
6463 static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
6464     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6465
6466     TRACE("Set render target %u to %p\n", idx, render_target);
6467
6468     if (render_target) {
6469         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, idx, render_target);
6470         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
6471     } else {
6472         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
6473         checkGLcall("glFramebufferTexture2DEXT()");
6474
6475         This->draw_buffers[idx] = GL_NONE;
6476     }
6477 }
6478
6479 static void check_fbo_status(IWineD3DDevice *iface) {
6480     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6481     GLenum status;
6482
6483     status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
6484     if (status == GL_FRAMEBUFFER_COMPLETE_EXT) {
6485         TRACE("FBO complete\n");
6486     } else {
6487         IWineD3DSurfaceImpl *attachment;
6488         int i;
6489         FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status);
6490
6491         /* Dump the FBO attachments */
6492         for (i = 0; i < GL_LIMITS(buffers); ++i) {
6493             attachment = (IWineD3DSurfaceImpl *)This->fbo_color_attachments[i];
6494             if (attachment) {
6495                 FIXME("\tColor attachment %d: (%p) %s %ux%u\n", i, attachment, debug_d3dformat(attachment->resource.format),
6496                         attachment->pow2Width, attachment->pow2Height);
6497             }
6498         }
6499         attachment = (IWineD3DSurfaceImpl *)This->fbo_depth_attachment;
6500         if (attachment) {
6501             FIXME("\tDepth attachment: (%p) %s %ux%u\n", attachment, debug_d3dformat(attachment->resource.format),
6502                     attachment->pow2Width, attachment->pow2Height);
6503         }
6504     }
6505 }
6506
6507 static BOOL depth_mismatch_fbo(IWineD3DDevice *iface) {
6508     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6509     IWineD3DSurfaceImpl *rt_impl = (IWineD3DSurfaceImpl *)This->render_targets[0];
6510     IWineD3DSurfaceImpl *ds_impl = (IWineD3DSurfaceImpl *)This->stencilBufferTarget;
6511
6512     if (!ds_impl) return FALSE;
6513
6514     if (ds_impl->current_renderbuffer) {
6515         return (rt_impl->pow2Width != ds_impl->current_renderbuffer->width ||
6516                 rt_impl->pow2Height != ds_impl->current_renderbuffer->height);
6517     }
6518
6519     return (rt_impl->pow2Width != ds_impl->pow2Width ||
6520             rt_impl->pow2Height != ds_impl->pow2Height);
6521 }
6522
6523 void apply_fbo_state(IWineD3DDevice *iface) {
6524     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6525     unsigned int i;
6526
6527     if (This->render_offscreen) {
6528         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6529
6530         /* Apply render targets */
6531         for (i = 0; i < GL_LIMITS(buffers); ++i) {
6532             IWineD3DSurface *render_target = This->render_targets[i];
6533             if (This->fbo_color_attachments[i] != render_target) {
6534                 set_render_target_fbo(iface, i, render_target);
6535                 This->fbo_color_attachments[i] = render_target;
6536             }
6537         }
6538
6539         /* Apply depth targets */
6540         if (This->fbo_depth_attachment != This->stencilBufferTarget || depth_mismatch_fbo(iface)) {
6541             unsigned int w = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Width;
6542             unsigned int h = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Height;
6543
6544             if (This->stencilBufferTarget) {
6545                 surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h);
6546             }
6547             set_depth_stencil_fbo(iface, This->stencilBufferTarget);
6548             This->fbo_depth_attachment = This->stencilBufferTarget;
6549         }
6550
6551         if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
6552             GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
6553             checkGLcall("glDrawBuffers()");
6554         } else {
6555             glDrawBuffer(This->draw_buffers[0]);
6556             checkGLcall("glDrawBuffer()");
6557         }
6558     } else {
6559         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6560     }
6561
6562     check_fbo_status(iface);
6563 }
6564
6565 void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect,
6566         IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) {
6567     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6568     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
6569     IWineD3DSwapChain *src_swapchain, *dst_swapchain;
6570     GLenum gl_filter;
6571
6572     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
6573             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
6574     TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2);
6575     TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2);
6576
6577     switch (filter) {
6578         case WINED3DTEXF_LINEAR:
6579             gl_filter = GL_LINEAR;
6580             break;
6581
6582         default:
6583             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
6584         case WINED3DTEXF_NONE:
6585         case WINED3DTEXF_POINT:
6586             gl_filter = GL_NEAREST;
6587             break;
6588     }
6589
6590     /* Attach src surface to src fbo */
6591     src_swapchain = get_swapchain(src_surface);
6592     if (src_swapchain) {
6593         GLenum buffer;
6594
6595         TRACE("Source surface %p is onscreen\n", src_surface);
6596         ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD);
6597         /* Make sure the drawable is up to date. In the offscreen case
6598          * attach_surface_fbo() implicitly takes care of this. */
6599         IWineD3DSurface_LoadLocation(src_surface, SFLAG_INDRAWABLE, NULL);
6600
6601         ENTER_GL();
6602         GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0));
6603         buffer = surface_get_gl_buffer(src_surface, src_swapchain);
6604         glReadBuffer(buffer);
6605         checkGLcall("glReadBuffer()");
6606
6607         src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
6608         src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
6609     } else {
6610         TRACE("Source surface %p is offscreen\n", src_surface);
6611         ENTER_GL();
6612         bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo);
6613         attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
6614         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
6615         checkGLcall("glReadBuffer()");
6616         GL_EXTCALL(glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
6617         checkGLcall("glFramebufferRenderbufferEXT");
6618     }
6619     LEAVE_GL();
6620
6621     /* Attach dst surface to dst fbo */
6622     dst_swapchain = get_swapchain(dst_surface);
6623     if (dst_swapchain) {
6624         GLenum buffer;
6625
6626         TRACE("Destination surface %p is onscreen\n", dst_surface);
6627         ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD);
6628         /* Make sure the drawable is up to date. In the offscreen case
6629          * attach_surface_fbo() implicitly takes care of this. */
6630         IWineD3DSurface_LoadLocation(dst_surface, SFLAG_INDRAWABLE, NULL);
6631
6632         ENTER_GL();
6633         GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0));
6634         buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
6635         glDrawBuffer(buffer);
6636         checkGLcall("glDrawBuffer()");
6637
6638         dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
6639         dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
6640     } else {
6641         TRACE("Destination surface %p is offscreen\n", dst_surface);
6642
6643         /* No src or dst swapchain? Make sure some context is active(multithreading) */
6644         if(!src_swapchain) {
6645             ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6646         }
6647
6648         ENTER_GL();
6649         bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo);
6650         attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
6651         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
6652         checkGLcall("glDrawBuffer()");
6653         GL_EXTCALL(glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
6654         checkGLcall("glFramebufferRenderbufferEXT");
6655     }
6656     glDisable(GL_SCISSOR_TEST);
6657     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6658
6659     if (flip) {
6660         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6661                 dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter));
6662         checkGLcall("glBlitFramebuffer()");
6663     } else {
6664         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6665                 dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter));
6666         checkGLcall("glBlitFramebuffer()");
6667     }
6668
6669     IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INDRAWABLE, TRUE);
6670
6671     if (This->render_offscreen) {
6672         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6673     } else {
6674         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6675         checkGLcall("glBindFramebuffer()");
6676     }
6677
6678     /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
6679     if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer
6680             && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) {
6681         glDrawBuffer(GL_BACK);
6682         checkGLcall("glDrawBuffer()");
6683     }
6684     LEAVE_GL();
6685 }
6686
6687 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6688     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6689     WINED3DVIEWPORT viewport;
6690
6691     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
6692
6693     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6694         WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
6695              This, RenderTargetIndex, GL_LIMITS(buffers));
6696         return WINED3DERR_INVALIDCALL;
6697     }
6698
6699     /* MSDN says that null disables the render target
6700     but a device must always be associated with a render target
6701     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6702     */
6703     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6704         FIXME("Trying to set render target 0 to NULL\n");
6705         return WINED3DERR_INVALIDCALL;
6706     }
6707     if (pRenderTarget && !(((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6708         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);
6709         return WINED3DERR_INVALIDCALL;
6710     }
6711
6712     /* If we are trying to set what we already have, don't bother */
6713     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
6714         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6715         return WINED3D_OK;
6716     }
6717     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
6718     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
6719     This->render_targets[RenderTargetIndex] = pRenderTarget;
6720
6721     /* Render target 0 is special */
6722     if(RenderTargetIndex == 0) {
6723         /* Finally, reset the viewport as the MSDN states. */
6724         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
6725         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
6726         viewport.X      = 0;
6727         viewport.Y      = 0;
6728         viewport.MaxZ   = 1.0f;
6729         viewport.MinZ   = 0.0f;
6730         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6731         /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
6732          * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
6733          */
6734         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
6735     }
6736     return WINED3D_OK;
6737 }
6738
6739 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6740     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6741     HRESULT  hr = WINED3D_OK;
6742     IWineD3DSurface *tmp;
6743
6744     TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This, This->stencilBufferTarget, pNewZStencil);
6745
6746     if (pNewZStencil == This->stencilBufferTarget) {
6747         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6748     } else {
6749         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead
6750         * depending on the renter target implementation being used.
6751         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6752         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6753         * stencil buffer and incur an extra memory overhead
6754          ******************************************************/
6755
6756         tmp = This->stencilBufferTarget;
6757         This->stencilBufferTarget = pNewZStencil;
6758         This->depth_copy_state = WINED3D_DCS_NO_COPY;
6759         /* should we be calling the parent or the wined3d surface? */
6760         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6761         if (NULL != tmp) IWineD3DSurface_Release(tmp);
6762         hr = WINED3D_OK;
6763
6764         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
6765             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
6766             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
6767             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
6768             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
6769         }
6770     }
6771
6772     return hr;
6773 }
6774
6775 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6776                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6777     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6778     /* TODO: the use of Impl is deprecated. */
6779     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6780     WINED3DLOCKED_RECT lockedRect;
6781
6782     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6783
6784     /* some basic validation checks */
6785     if(This->cursorTexture) {
6786         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6787         ENTER_GL();
6788         glDeleteTextures(1, &This->cursorTexture);
6789         LEAVE_GL();
6790         This->cursorTexture = 0;
6791     }
6792
6793     if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
6794         This->haveHardwareCursor = TRUE;
6795     else
6796         This->haveHardwareCursor = FALSE;
6797
6798     if(pCursorBitmap) {
6799         WINED3DLOCKED_RECT rect;
6800
6801         /* MSDN: Cursor must be A8R8G8B8 */
6802         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6803             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6804             return WINED3DERR_INVALIDCALL;
6805         }
6806
6807         /* MSDN: Cursor must be smaller than the display mode */
6808         if(pSur->currentDesc.Width > This->ddraw_width ||
6809            pSur->currentDesc.Height > This->ddraw_height) {
6810             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);
6811             return WINED3DERR_INVALIDCALL;
6812         }
6813
6814         if (!This->haveHardwareCursor) {
6815             /* TODO: MSDN: Cursor sizes must be a power of 2 */
6816
6817             /* Do not store the surface's pointer because the application may
6818              * release it after setting the cursor image. Windows doesn't
6819              * addref the set surface, so we can't do this either without
6820              * creating circular refcount dependencies. Copy out the gl texture
6821              * instead.
6822              */
6823             This->cursorWidth = pSur->currentDesc.Width;
6824             This->cursorHeight = pSur->currentDesc.Height;
6825             if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
6826             {
6827                 const GlPixelFormatDesc *glDesc;
6828                 const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(WINED3DFMT_A8R8G8B8, &GLINFO_LOCATION, &glDesc);
6829                 char *mem, *bits = (char *)rect.pBits;
6830                 GLint intfmt = glDesc->glInternal;
6831                 GLint format = glDesc->glFormat;
6832                 GLint type = glDesc->glType;
6833                 INT height = This->cursorHeight;
6834                 INT width = This->cursorWidth;
6835                 INT bpp = tableEntry->bpp;
6836                 INT i;
6837
6838                 /* Reformat the texture memory (pitch and width can be
6839                  * different) */
6840                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
6841                 for(i = 0; i < height; i++)
6842                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
6843                 IWineD3DSurface_UnlockRect(pCursorBitmap);
6844                 ENTER_GL();
6845
6846                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6847                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
6848                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6849                 }
6850
6851                 /* Make sure that a proper texture unit is selected */
6852                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
6853                     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
6854                     checkGLcall("glActiveTextureARB");
6855                 }
6856                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
6857                 /* Create a new cursor texture */
6858                 glGenTextures(1, &This->cursorTexture);
6859                 checkGLcall("glGenTextures");
6860                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
6861                 checkGLcall("glBindTexture");
6862                 /* Copy the bitmap memory into the cursor texture */
6863                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
6864                 HeapFree(GetProcessHeap(), 0, mem);
6865                 checkGLcall("glTexImage2D");
6866
6867                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6868                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
6869                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6870                 }
6871
6872                 LEAVE_GL();
6873             }
6874             else
6875             {
6876                 FIXME("A cursor texture was not returned.\n");
6877                 This->cursorTexture = 0;
6878             }
6879         }
6880         else
6881         {
6882             /* Draw a hardware cursor */
6883             ICONINFO cursorInfo;
6884             HCURSOR cursor;
6885             /* Create and clear maskBits because it is not needed for
6886              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
6887              * chunks. */
6888             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6889                 (pSur->currentDesc.Width * pSur->currentDesc.Height / 8));
6890             IWineD3DSurface_LockRect(pCursorBitmap, &lockedRect, NULL,
6891                                          WINED3DLOCK_NO_DIRTY_UPDATE |
6892                                          WINED3DLOCK_READONLY
6893             );
6894             TRACE("width: %i height: %i\n", pSur->currentDesc.Width,
6895                   pSur->currentDesc.Height);
6896
6897             cursorInfo.fIcon = FALSE;
6898             cursorInfo.xHotspot = XHotSpot;
6899             cursorInfo.yHotspot = YHotSpot;
6900             cursorInfo.hbmMask = CreateBitmap(pSur->currentDesc.Width,
6901                                               pSur->currentDesc.Height, 1,
6902                                               1, &maskBits);
6903             cursorInfo.hbmColor = CreateBitmap(pSur->currentDesc.Width,
6904                                                pSur->currentDesc.Height, 1,
6905                                                32, lockedRect.pBits);
6906             IWineD3DSurface_UnlockRect(pCursorBitmap);
6907             /* Create our cursor and clean up. */
6908             cursor = CreateIconIndirect(&cursorInfo);
6909             SetCursor(cursor);
6910             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
6911             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
6912             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
6913             This->hardwareCursor = cursor;
6914             HeapFree(GetProcessHeap(), 0, maskBits);
6915         }
6916     }
6917
6918     This->xHotSpot = XHotSpot;
6919     This->yHotSpot = YHotSpot;
6920     return WINED3D_OK;
6921 }
6922
6923 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6924     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6925     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6926
6927     This->xScreenSpace = XScreenSpace;
6928     This->yScreenSpace = YScreenSpace;
6929
6930     return;
6931
6932 }
6933
6934 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6935     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6936     BOOL oldVisible = This->bCursorVisible;
6937     POINT pt;
6938
6939     TRACE("(%p) : visible(%d)\n", This, bShow);
6940
6941     /*
6942      * When ShowCursor is first called it should make the cursor appear at the OS's last
6943      * known cursor position.  Because of this, some applications just repetitively call
6944      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
6945      */
6946     GetCursorPos(&pt);
6947     This->xScreenSpace = pt.x;
6948     This->yScreenSpace = pt.y;
6949
6950     if (This->haveHardwareCursor) {
6951         This->bCursorVisible = bShow;
6952         if (bShow)
6953             SetCursor(This->hardwareCursor);
6954         else
6955             SetCursor(NULL);
6956     }
6957     else
6958     {
6959         if (This->cursorTexture)
6960             This->bCursorVisible = bShow;
6961     }
6962
6963     return oldVisible;
6964 }
6965
6966 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6967     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6968     IWineD3DResourceImpl *resource;
6969     TRACE("(%p) : state (%u)\n", This, This->state);
6970
6971     /* TODO: Implement wrapping of the WndProc so that mimimize and maximize can be monitored and the states adjusted. */
6972     switch (This->state) {
6973     case WINED3D_OK:
6974         return WINED3D_OK;
6975     case WINED3DERR_DEVICELOST:
6976         {
6977             LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
6978                 if (resource->resource.pool == WINED3DPOOL_DEFAULT)
6979                     return WINED3DERR_DEVICENOTRESET;
6980             }
6981             return WINED3DERR_DEVICELOST;
6982         }
6983     case WINED3DERR_DRIVERINTERNALERROR:
6984         return WINED3DERR_DRIVERINTERNALERROR;
6985     }
6986
6987     /* Unknown state */
6988     return WINED3DERR_DRIVERINTERNALERROR;
6989 }
6990
6991
6992 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6993     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6994     /** FIXME: Resource tracking needs to be done,
6995     * The closes we can do to this is set the priorities of all managed textures low
6996     * and then reset them.
6997      ***********************************************************/
6998     FIXME("(%p) : stub\n", This);
6999     return WINED3D_OK;
7000 }
7001
7002 static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7003     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
7004
7005     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
7006     if(surface->Flags & SFLAG_DIBSECTION) {
7007         /* Release the DC */
7008         SelectObject(surface->hDC, surface->dib.holdbitmap);
7009         DeleteDC(surface->hDC);
7010         /* Release the DIB section */
7011         DeleteObject(surface->dib.DIBsection);
7012         surface->dib.bitmap_data = NULL;
7013         surface->resource.allocatedMemory = NULL;
7014         surface->Flags &= ~SFLAG_DIBSECTION;
7015     }
7016     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
7017     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
7018     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
7019         surface->pow2Width = pPresentationParameters->BackBufferWidth;
7020         surface->pow2Height = pPresentationParameters->BackBufferHeight;
7021     } else {
7022         surface->pow2Width = surface->pow2Height = 1;
7023         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
7024         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
7025     }
7026     surface->glRect.left = 0;
7027     surface->glRect.top = 0;
7028     surface->glRect.right = surface->pow2Width;
7029     surface->glRect.bottom = surface->pow2Height;
7030
7031     if(surface->glDescription.textureName) {
7032         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
7033         ENTER_GL();
7034         glDeleteTextures(1, &surface->glDescription.textureName);
7035         LEAVE_GL();
7036         surface->glDescription.textureName = 0;
7037         surface->Flags &= ~SFLAG_CLIENT;
7038     }
7039     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
7040        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
7041         surface->Flags |= SFLAG_NONPOW2;
7042     } else  {
7043         surface->Flags &= ~SFLAG_NONPOW2;
7044     }
7045     HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
7046     surface->resource.allocatedMemory = NULL;
7047     surface->resource.heapMemory = NULL;
7048     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
7049     /* INDRAWABLE is a sane place for implicit targets after the reset, INSYSMEM is more appropriate for depth stencils. */
7050     if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) {
7051         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INSYSMEM, TRUE);
7052     } else {
7053         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) surface, SFLAG_INDRAWABLE, TRUE);
7054     }
7055 }
7056
7057 static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) {
7058     TRACE("Unloading resource %p\n", resource);
7059     IWineD3DResource_UnLoad(resource);
7060     IWineD3DResource_Release(resource);
7061     return S_OK;
7062 }
7063
7064 static void reset_fbo_state(IWineD3DDevice *iface) {
7065     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7066     unsigned int i;
7067
7068     ENTER_GL();
7069     GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
7070     checkGLcall("glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)");
7071
7072     if (This->fbo) {
7073         GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
7074         This->fbo = 0;
7075     }
7076     if (This->src_fbo) {
7077         GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->src_fbo));
7078         This->src_fbo = 0;
7079     }
7080     if (This->dst_fbo) {
7081         GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->dst_fbo));
7082         This->dst_fbo = 0;
7083     }
7084     checkGLcall("Tear down FBOs\n");
7085     LEAVE_GL();
7086
7087     for (i = 0; i < GL_LIMITS(buffers); ++i) {
7088         This->fbo_color_attachments[i] = NULL;
7089     }
7090     This->fbo_depth_attachment = NULL;
7091 }
7092
7093 static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, WINED3DPRESENT_PARAMETERS *pp) {
7094     UINT i, count;
7095     WINED3DDISPLAYMODE m;
7096     HRESULT hr;
7097
7098     /* All Windowed modes are supported, as is leaving the current mode */
7099     if(pp->Windowed) return TRUE;
7100     if(!pp->BackBufferWidth) return TRUE;
7101     if(!pp->BackBufferHeight) return TRUE;
7102
7103     count = IWineD3D_GetAdapterModeCount(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN);
7104     for(i = 0; i < count; i++) {
7105         memset(&m, 0, sizeof(m));
7106         hr = IWineD3D_EnumAdapterModes(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN, i, &m);
7107         if(FAILED(hr)) {
7108             ERR("EnumAdapterModes failed\n");
7109         }
7110         if(m.Width == pp->BackBufferWidth && m.Height == pp->BackBufferHeight) {
7111             /* Mode found, it is supported */
7112             return TRUE;
7113         }
7114     }
7115     /* Mode not found -> not supported */
7116     return FALSE;
7117 }
7118
7119 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
7120     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7121     IWineD3DSwapChainImpl *swapchain;
7122     HRESULT hr;
7123     BOOL DisplayModeChanged = FALSE;
7124     WINED3DDISPLAYMODE mode;
7125     IWineD3DBaseShaderImpl *shader;
7126     IWineD3DSurfaceImpl *target;
7127     UINT i;
7128     TRACE("(%p)\n", This);
7129
7130     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
7131     if(FAILED(hr)) {
7132         ERR("Failed to get the first implicit swapchain\n");
7133         return hr;
7134     }
7135
7136     if(!is_display_mode_supported(This, pPresentationParameters)) {
7137         WARN("Rejecting Reset() call because the requested display mode is not supported\n");
7138         WARN("Requested mode: %d, %d\n", pPresentationParameters->BackBufferWidth,
7139              pPresentationParameters->BackBufferHeight);
7140         return WINED3DERR_INVALIDCALL;
7141     }
7142
7143     /* Is it necessary to recreate the gl context? Actually every setting can be changed
7144      * on an existing gl context, so there's no real need for recreation.
7145      *
7146      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
7147      *
7148      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
7149      */
7150     TRACE("New params:\n");
7151     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
7152     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
7153     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
7154     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
7155     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
7156     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
7157     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
7158     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
7159     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
7160     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
7161     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
7162     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
7163     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
7164
7165     /* No special treatment of these parameters. Just store them */
7166     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
7167     swapchain->presentParms.Flags = pPresentationParameters->Flags;
7168     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
7169     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
7170
7171     /* What to do about these? */
7172     if(pPresentationParameters->BackBufferCount != 0 &&
7173         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
7174         ERR("Cannot change the back buffer count yet\n");
7175     }
7176     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
7177         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
7178         ERR("Cannot change the back buffer format yet\n");
7179     }
7180     if(pPresentationParameters->hDeviceWindow != NULL &&
7181         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
7182         ERR("Cannot change the device window yet\n");
7183     }
7184     if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
7185         ERR("What do do about a changed auto depth stencil parameter?\n");
7186     }
7187
7188     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
7189         reset_fbo_state((IWineD3DDevice *) This);
7190     }
7191
7192     IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL);
7193     LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) {
7194         This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader);
7195     }
7196
7197     ENTER_GL();
7198     if(This->depth_blt_texture) {
7199         glDeleteTextures(1, &This->depth_blt_texture);
7200         This->depth_blt_texture = 0;
7201     }
7202     This->shader_backend->shader_destroy_depth_blt(iface);
7203     This->shader_backend->shader_free_private(iface);
7204
7205     for (i = 0; i < GL_LIMITS(textures); i++) {
7206         /* Textures are recreated below */
7207         glDeleteTextures(1, &This->dummyTextureName[i]);
7208         checkGLcall("glDeleteTextures(1, &This->dummyTextureName[i])");
7209         This->dummyTextureName[i] = 0;
7210     }
7211     LEAVE_GL();
7212
7213     while(This->numContexts) {
7214         DestroyContext(This, This->contexts[0]);
7215     }
7216     This->activeContext = NULL;
7217     HeapFree(GetProcessHeap(), 0, swapchain->context);
7218     swapchain->context = NULL;
7219     swapchain->num_contexts = 0;
7220
7221      if(pPresentationParameters->Windowed) {
7222         mode.Width = swapchain->orig_width;
7223         mode.Height = swapchain->orig_height;
7224         mode.RefreshRate = 0;
7225         mode.Format = swapchain->presentParms.BackBufferFormat;
7226     } else {
7227         mode.Width = pPresentationParameters->BackBufferWidth;
7228         mode.Height = pPresentationParameters->BackBufferHeight;
7229         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
7230         mode.Format = swapchain->presentParms.BackBufferFormat;
7231     }
7232
7233     /* Should Width == 800 && Height == 0 set 800x600? */
7234     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
7235        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
7236         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
7237     {
7238         WINED3DVIEWPORT vp;
7239         int i;
7240
7241         vp.X = 0;
7242         vp.Y = 0;
7243         vp.Width = pPresentationParameters->BackBufferWidth;
7244         vp.Height = pPresentationParameters->BackBufferHeight;
7245         vp.MinZ = 0;
7246         vp.MaxZ = 1;
7247
7248         if(!pPresentationParameters->Windowed) {
7249             DisplayModeChanged = TRUE;
7250         }
7251         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
7252         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
7253
7254         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
7255         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
7256             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
7257         }
7258         if(This->auto_depth_stencil_buffer) {
7259             updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters);
7260         }
7261
7262
7263         /* Now set the new viewport */
7264         IWineD3DDevice_SetViewport(iface, &vp);
7265     }
7266
7267     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
7268        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
7269         DisplayModeChanged) {
7270
7271         IWineD3DDevice_SetFullscreen(iface, !pPresentationParameters->Windowed);
7272         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
7273         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
7274     } else if(!pPresentationParameters->Windowed) {
7275         DWORD style = This->style, exStyle = This->exStyle;
7276         /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
7277          * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
7278          * Reset to clear up their mess. Guild Wars also loses the device during that.
7279          */
7280         This->style = 0;
7281         This->exStyle = 0;
7282         IWineD3DDeviceImpl_SetupFullscreenWindow(iface, This->ddraw_window);
7283         This->style = style;
7284         This->exStyle = exStyle;
7285     }
7286
7287     /* Recreate the primary swapchain's context */
7288     swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
7289     if(swapchain->backBuffer) {
7290         target = (IWineD3DSurfaceImpl *) swapchain->backBuffer[0];
7291     } else {
7292         target = (IWineD3DSurfaceImpl *) swapchain->frontBuffer;
7293     }
7294     swapchain->context[0] = CreateContext(This, target, swapchain->win_handle, FALSE,
7295                                           &swapchain->presentParms);
7296     swapchain->num_contexts = 1;
7297     This->activeContext = swapchain->context[0];
7298     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
7299
7300     hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock);
7301     if(FAILED(hr)) {
7302         ERR("Resetting the stateblock failed with error 0x%08x\n", hr);
7303     }
7304     create_dummy_textures(This);
7305
7306
7307     hr = This->shader_backend->shader_alloc_private(iface);
7308     if(FAILED(hr)) {
7309         ERR("Failed to recreate shader private data\n");
7310         return hr;
7311     }
7312
7313     /* All done. There is no need to reload resources or shaders, this will happen automatically on the
7314      * first use
7315      */
7316     return WINED3D_OK;
7317 }
7318
7319 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
7320     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7321     /** FIXME: always true at the moment **/
7322     if(!bEnableDialogs) {
7323         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
7324     }
7325     return WINED3D_OK;
7326 }
7327
7328
7329 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
7330     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7331     TRACE("(%p) : pParameters %p\n", This, pParameters);
7332
7333     *pParameters = This->createParms;
7334     return WINED3D_OK;
7335 }
7336
7337 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
7338     IWineD3DSwapChain *swapchain;
7339
7340     TRACE("Relaying  to swapchain\n");
7341
7342     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
7343         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
7344         IWineD3DSwapChain_Release(swapchain);
7345     }
7346     return;
7347 }
7348
7349 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
7350     IWineD3DSwapChain *swapchain;
7351
7352     TRACE("Relaying  to swapchain\n");
7353
7354     if (IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain) == WINED3D_OK) {
7355         IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
7356         IWineD3DSwapChain_Release(swapchain);
7357     }
7358     return;
7359 }
7360
7361
7362 /** ********************************************************
7363 *   Notification functions
7364 ** ********************************************************/
7365 /** This function must be called in the release of a resource when ref == 0,
7366 * the contents of resource must still be correct,
7367 * any handles to other resource held by the caller must be closed
7368 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7369  *****************************************************/
7370 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7371     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7372
7373     TRACE("(%p) : Adding Resource %p\n", This, resource);
7374     list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
7375 }
7376
7377 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
7378     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
7379
7380     TRACE("(%p) : Removing resource %p\n", This, resource);
7381
7382     list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
7383 }
7384
7385
7386 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7387     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7388     int counter;
7389
7390     TRACE("(%p) : resource %p\n", This, resource);
7391     switch(IWineD3DResource_GetType(resource)){
7392         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
7393         case WINED3DRTYPE_SURFACE: {
7394             unsigned int i;
7395
7396             /* Cleanup any FBO attachments if d3d is enabled */
7397             if(This->d3d_initialized) {
7398                 if((IWineD3DSurface *)resource == This->lastActiveRenderTarget) {
7399                     IWineD3DSwapChainImpl *swapchain = This->swapchains ? (IWineD3DSwapChainImpl *) This->swapchains[0] : NULL;
7400
7401                     TRACE("Last active render target destroyed\n");
7402                     /* Find a replacement surface for the currently active back buffer. The context manager does not do NULL
7403                      * checks, so switch to a valid target as long as the currently set surface is still valid. Use the
7404                      * surface of the implicit swpchain. If that is the same as the destroyed surface the device is destroyed
7405                      * and the lastActiveRenderTarget member shouldn't matter
7406                      */
7407                     if(swapchain) {
7408                         if(swapchain->backBuffer && swapchain->backBuffer[0] != (IWineD3DSurface *)resource) {
7409                             TRACE("Activating primary back buffer\n");
7410                             ActivateContext(This, swapchain->backBuffer[0], CTXUSAGE_RESOURCELOAD);
7411                         } else if(!swapchain->backBuffer && swapchain->frontBuffer != (IWineD3DSurface *)resource) {
7412                             /* Single buffering environment */
7413                             TRACE("Activating primary front buffer\n");
7414                             ActivateContext(This, swapchain->frontBuffer, CTXUSAGE_RESOURCELOAD);
7415                         } else {
7416                             TRACE("Device is being destroyed, setting lastActiveRenderTarget = 0xdeadbabe\n");
7417                             /* Implicit render target destroyed, that means the device is being destroyed
7418                              * whatever we set here, it shouldn't matter
7419                              */
7420                             This->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadbabe;
7421                         }
7422                     } else {
7423                         /* May happen during ddraw uninitialization */
7424                         TRACE("Render target set, but swapchain does not exist!\n");
7425                         This->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadcafe;
7426                     }
7427                 }
7428
7429                 ENTER_GL();
7430                 for (i = 0; i < GL_LIMITS(buffers); ++i) {
7431                     if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) {
7432                         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
7433                         set_render_target_fbo(iface, i, NULL);
7434                         This->fbo_color_attachments[i] = NULL;
7435                     }
7436                 }
7437                 if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) {
7438                     bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
7439                     set_depth_stencil_fbo(iface, NULL);
7440                     This->fbo_depth_attachment = NULL;
7441                 }
7442                 LEAVE_GL();
7443             }
7444
7445             break;
7446         }
7447         case WINED3DRTYPE_TEXTURE:
7448         case WINED3DRTYPE_CUBETEXTURE:
7449         case WINED3DRTYPE_VOLUMETEXTURE:
7450                 for (counter = 0; counter < MAX_COMBINED_SAMPLERS; counter++) {
7451                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7452                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7453                         This->stateBlock->textures[counter] = NULL;
7454                     }
7455                     if (This->updateStateBlock != This->stateBlock ){
7456                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7457                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7458                             This->updateStateBlock->textures[counter] = NULL;
7459                         }
7460                     }
7461                 }
7462         break;
7463         case WINED3DRTYPE_VOLUME:
7464         /* TODO: nothing really? */
7465         break;
7466         case WINED3DRTYPE_VERTEXBUFFER:
7467         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7468         {
7469             int streamNumber;
7470             TRACE("Cleaning up stream pointers\n");
7471
7472             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7473                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7474                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7475                 */
7476                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7477                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7478                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7479                         This->updateStateBlock->streamSource[streamNumber] = 0;
7480                         /* Set changed flag? */
7481                     }
7482                 }
7483                 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) */
7484                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7485                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7486                         This->stateBlock->streamSource[streamNumber] = 0;
7487                     }
7488                 }
7489 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7490                  else { /* This shouldn't happen */
7491                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7492                 }
7493 #endif
7494
7495             }
7496         }
7497         break;
7498         case WINED3DRTYPE_INDEXBUFFER:
7499         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7500         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7501             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7502                 This->updateStateBlock->pIndexData =  NULL;
7503             }
7504         }
7505         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7506             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7507                 This->stateBlock->pIndexData =  NULL;
7508             }
7509         }
7510
7511         break;
7512         default:
7513         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7514         break;
7515     }
7516
7517
7518     /* Remove the resource from the resourceStore */
7519     IWineD3DDeviceImpl_RemoveResource(iface, resource);
7520
7521     TRACE("Resource released\n");
7522
7523 }
7524
7525 static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
7526     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7527     IWineD3DResourceImpl *resource, *cursor;
7528     HRESULT ret;
7529     TRACE("(%p)->(%p,%p)\n", This, pCallback, pData);
7530
7531     LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
7532         TRACE("enumerating resource %p\n", resource);
7533         IWineD3DResource_AddRef((IWineD3DResource *) resource);
7534         ret = pCallback((IWineD3DResource *) resource, pData);
7535         if(ret == S_FALSE) {
7536             TRACE("Canceling enumeration\n");
7537             break;
7538         }
7539     }
7540     return WINED3D_OK;
7541 }
7542
7543 /**********************************************************
7544  * IWineD3DDevice VTbl follows
7545  **********************************************************/
7546
7547 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7548 {
7549     /*** IUnknown methods ***/
7550     IWineD3DDeviceImpl_QueryInterface,
7551     IWineD3DDeviceImpl_AddRef,
7552     IWineD3DDeviceImpl_Release,
7553     /*** IWineD3DDevice methods ***/
7554     IWineD3DDeviceImpl_GetParent,
7555     /*** Creation methods**/
7556     IWineD3DDeviceImpl_CreateVertexBuffer,
7557     IWineD3DDeviceImpl_CreateIndexBuffer,
7558     IWineD3DDeviceImpl_CreateStateBlock,
7559     IWineD3DDeviceImpl_CreateSurface,
7560     IWineD3DDeviceImpl_CreateTexture,
7561     IWineD3DDeviceImpl_CreateVolumeTexture,
7562     IWineD3DDeviceImpl_CreateVolume,
7563     IWineD3DDeviceImpl_CreateCubeTexture,
7564     IWineD3DDeviceImpl_CreateQuery,
7565     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7566     IWineD3DDeviceImpl_CreateVertexDeclaration,
7567     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
7568     IWineD3DDeviceImpl_CreateVertexShader,
7569     IWineD3DDeviceImpl_CreatePixelShader,
7570     IWineD3DDeviceImpl_CreatePalette,
7571     /*** Odd functions **/
7572     IWineD3DDeviceImpl_Init3D,
7573     IWineD3DDeviceImpl_Uninit3D,
7574     IWineD3DDeviceImpl_SetFullscreen,
7575     IWineD3DDeviceImpl_SetMultithreaded,
7576     IWineD3DDeviceImpl_EvictManagedResources,
7577     IWineD3DDeviceImpl_GetAvailableTextureMem,
7578     IWineD3DDeviceImpl_GetBackBuffer,
7579     IWineD3DDeviceImpl_GetCreationParameters,
7580     IWineD3DDeviceImpl_GetDeviceCaps,
7581     IWineD3DDeviceImpl_GetDirect3D,
7582     IWineD3DDeviceImpl_GetDisplayMode,
7583     IWineD3DDeviceImpl_SetDisplayMode,
7584     IWineD3DDeviceImpl_GetHWND,
7585     IWineD3DDeviceImpl_SetHWND,
7586     IWineD3DDeviceImpl_GetNumberOfSwapChains,
7587     IWineD3DDeviceImpl_GetRasterStatus,
7588     IWineD3DDeviceImpl_GetSwapChain,
7589     IWineD3DDeviceImpl_Reset,
7590     IWineD3DDeviceImpl_SetDialogBoxMode,
7591     IWineD3DDeviceImpl_SetCursorProperties,
7592     IWineD3DDeviceImpl_SetCursorPosition,
7593     IWineD3DDeviceImpl_ShowCursor,
7594     IWineD3DDeviceImpl_TestCooperativeLevel,
7595     /*** Getters and setters **/
7596     IWineD3DDeviceImpl_SetClipPlane,
7597     IWineD3DDeviceImpl_GetClipPlane,
7598     IWineD3DDeviceImpl_SetClipStatus,
7599     IWineD3DDeviceImpl_GetClipStatus,
7600     IWineD3DDeviceImpl_SetCurrentTexturePalette,
7601     IWineD3DDeviceImpl_GetCurrentTexturePalette,
7602     IWineD3DDeviceImpl_SetDepthStencilSurface,
7603     IWineD3DDeviceImpl_GetDepthStencilSurface,
7604     IWineD3DDeviceImpl_SetFVF,
7605     IWineD3DDeviceImpl_GetFVF,
7606     IWineD3DDeviceImpl_SetGammaRamp,
7607     IWineD3DDeviceImpl_GetGammaRamp,
7608     IWineD3DDeviceImpl_SetIndices,
7609     IWineD3DDeviceImpl_GetIndices,
7610     IWineD3DDeviceImpl_SetBaseVertexIndex,
7611     IWineD3DDeviceImpl_GetBaseVertexIndex,
7612     IWineD3DDeviceImpl_SetLight,
7613     IWineD3DDeviceImpl_GetLight,
7614     IWineD3DDeviceImpl_SetLightEnable,
7615     IWineD3DDeviceImpl_GetLightEnable,
7616     IWineD3DDeviceImpl_SetMaterial,
7617     IWineD3DDeviceImpl_GetMaterial,
7618     IWineD3DDeviceImpl_SetNPatchMode,
7619     IWineD3DDeviceImpl_GetNPatchMode,
7620     IWineD3DDeviceImpl_SetPaletteEntries,
7621     IWineD3DDeviceImpl_GetPaletteEntries,
7622     IWineD3DDeviceImpl_SetPixelShader,
7623     IWineD3DDeviceImpl_GetPixelShader,
7624     IWineD3DDeviceImpl_SetPixelShaderConstantB,
7625     IWineD3DDeviceImpl_GetPixelShaderConstantB,
7626     IWineD3DDeviceImpl_SetPixelShaderConstantI,
7627     IWineD3DDeviceImpl_GetPixelShaderConstantI,
7628     IWineD3DDeviceImpl_SetPixelShaderConstantF,
7629     IWineD3DDeviceImpl_GetPixelShaderConstantF,
7630     IWineD3DDeviceImpl_SetRenderState,
7631     IWineD3DDeviceImpl_GetRenderState,
7632     IWineD3DDeviceImpl_SetRenderTarget,
7633     IWineD3DDeviceImpl_GetRenderTarget,
7634     IWineD3DDeviceImpl_SetFrontBackBuffers,
7635     IWineD3DDeviceImpl_SetSamplerState,
7636     IWineD3DDeviceImpl_GetSamplerState,
7637     IWineD3DDeviceImpl_SetScissorRect,
7638     IWineD3DDeviceImpl_GetScissorRect,
7639     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7640     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7641     IWineD3DDeviceImpl_SetStreamSource,
7642     IWineD3DDeviceImpl_GetStreamSource,
7643     IWineD3DDeviceImpl_SetStreamSourceFreq,
7644     IWineD3DDeviceImpl_GetStreamSourceFreq,
7645     IWineD3DDeviceImpl_SetTexture,
7646     IWineD3DDeviceImpl_GetTexture,
7647     IWineD3DDeviceImpl_SetTextureStageState,
7648     IWineD3DDeviceImpl_GetTextureStageState,
7649     IWineD3DDeviceImpl_SetTransform,
7650     IWineD3DDeviceImpl_GetTransform,
7651     IWineD3DDeviceImpl_SetVertexDeclaration,
7652     IWineD3DDeviceImpl_GetVertexDeclaration,
7653     IWineD3DDeviceImpl_SetVertexShader,
7654     IWineD3DDeviceImpl_GetVertexShader,
7655     IWineD3DDeviceImpl_SetVertexShaderConstantB,
7656     IWineD3DDeviceImpl_GetVertexShaderConstantB,
7657     IWineD3DDeviceImpl_SetVertexShaderConstantI,
7658     IWineD3DDeviceImpl_GetVertexShaderConstantI,
7659     IWineD3DDeviceImpl_SetVertexShaderConstantF,
7660     IWineD3DDeviceImpl_GetVertexShaderConstantF,
7661     IWineD3DDeviceImpl_SetViewport,
7662     IWineD3DDeviceImpl_GetViewport,
7663     IWineD3DDeviceImpl_MultiplyTransform,
7664     IWineD3DDeviceImpl_ValidateDevice,
7665     IWineD3DDeviceImpl_ProcessVertices,
7666     /*** State block ***/
7667     IWineD3DDeviceImpl_BeginStateBlock,
7668     IWineD3DDeviceImpl_EndStateBlock,
7669     /*** Scene management ***/
7670     IWineD3DDeviceImpl_BeginScene,
7671     IWineD3DDeviceImpl_EndScene,
7672     IWineD3DDeviceImpl_Present,
7673     IWineD3DDeviceImpl_Clear,
7674     /*** Drawing ***/
7675     IWineD3DDeviceImpl_DrawPrimitive,
7676     IWineD3DDeviceImpl_DrawIndexedPrimitive,
7677     IWineD3DDeviceImpl_DrawPrimitiveUP,
7678     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7679     IWineD3DDeviceImpl_DrawPrimitiveStrided,
7680     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
7681     IWineD3DDeviceImpl_DrawRectPatch,
7682     IWineD3DDeviceImpl_DrawTriPatch,
7683     IWineD3DDeviceImpl_DeletePatch,
7684     IWineD3DDeviceImpl_ColorFill,
7685     IWineD3DDeviceImpl_UpdateTexture,
7686     IWineD3DDeviceImpl_UpdateSurface,
7687     IWineD3DDeviceImpl_GetFrontBufferData,
7688     /*** object tracking ***/
7689     IWineD3DDeviceImpl_ResourceReleased,
7690     IWineD3DDeviceImpl_EnumResources
7691 };
7692
7693 const IWineD3DDeviceVtbl IWineD3DDevice_DirtyConst_Vtbl =
7694 {
7695     /*** IUnknown methods ***/
7696     IWineD3DDeviceImpl_QueryInterface,
7697     IWineD3DDeviceImpl_AddRef,
7698     IWineD3DDeviceImpl_Release,
7699     /*** IWineD3DDevice methods ***/
7700     IWineD3DDeviceImpl_GetParent,
7701     /*** Creation methods**/
7702     IWineD3DDeviceImpl_CreateVertexBuffer,
7703     IWineD3DDeviceImpl_CreateIndexBuffer,
7704     IWineD3DDeviceImpl_CreateStateBlock,
7705     IWineD3DDeviceImpl_CreateSurface,
7706     IWineD3DDeviceImpl_CreateTexture,
7707     IWineD3DDeviceImpl_CreateVolumeTexture,
7708     IWineD3DDeviceImpl_CreateVolume,
7709     IWineD3DDeviceImpl_CreateCubeTexture,
7710     IWineD3DDeviceImpl_CreateQuery,
7711     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7712     IWineD3DDeviceImpl_CreateVertexDeclaration,
7713     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
7714     IWineD3DDeviceImpl_CreateVertexShader,
7715     IWineD3DDeviceImpl_CreatePixelShader,
7716     IWineD3DDeviceImpl_CreatePalette,
7717     /*** Odd functions **/
7718     IWineD3DDeviceImpl_Init3D,
7719     IWineD3DDeviceImpl_Uninit3D,
7720     IWineD3DDeviceImpl_SetFullscreen,
7721     IWineD3DDeviceImpl_SetMultithreaded,
7722     IWineD3DDeviceImpl_EvictManagedResources,
7723     IWineD3DDeviceImpl_GetAvailableTextureMem,
7724     IWineD3DDeviceImpl_GetBackBuffer,
7725     IWineD3DDeviceImpl_GetCreationParameters,
7726     IWineD3DDeviceImpl_GetDeviceCaps,
7727     IWineD3DDeviceImpl_GetDirect3D,
7728     IWineD3DDeviceImpl_GetDisplayMode,
7729     IWineD3DDeviceImpl_SetDisplayMode,
7730     IWineD3DDeviceImpl_GetHWND,
7731     IWineD3DDeviceImpl_SetHWND,
7732     IWineD3DDeviceImpl_GetNumberOfSwapChains,
7733     IWineD3DDeviceImpl_GetRasterStatus,
7734     IWineD3DDeviceImpl_GetSwapChain,
7735     IWineD3DDeviceImpl_Reset,
7736     IWineD3DDeviceImpl_SetDialogBoxMode,
7737     IWineD3DDeviceImpl_SetCursorProperties,
7738     IWineD3DDeviceImpl_SetCursorPosition,
7739     IWineD3DDeviceImpl_ShowCursor,
7740     IWineD3DDeviceImpl_TestCooperativeLevel,
7741     /*** Getters and setters **/
7742     IWineD3DDeviceImpl_SetClipPlane,
7743     IWineD3DDeviceImpl_GetClipPlane,
7744     IWineD3DDeviceImpl_SetClipStatus,
7745     IWineD3DDeviceImpl_GetClipStatus,
7746     IWineD3DDeviceImpl_SetCurrentTexturePalette,
7747     IWineD3DDeviceImpl_GetCurrentTexturePalette,
7748     IWineD3DDeviceImpl_SetDepthStencilSurface,
7749     IWineD3DDeviceImpl_GetDepthStencilSurface,
7750     IWineD3DDeviceImpl_SetFVF,
7751     IWineD3DDeviceImpl_GetFVF,
7752     IWineD3DDeviceImpl_SetGammaRamp,
7753     IWineD3DDeviceImpl_GetGammaRamp,
7754     IWineD3DDeviceImpl_SetIndices,
7755     IWineD3DDeviceImpl_GetIndices,
7756     IWineD3DDeviceImpl_SetBaseVertexIndex,
7757     IWineD3DDeviceImpl_GetBaseVertexIndex,
7758     IWineD3DDeviceImpl_SetLight,
7759     IWineD3DDeviceImpl_GetLight,
7760     IWineD3DDeviceImpl_SetLightEnable,
7761     IWineD3DDeviceImpl_GetLightEnable,
7762     IWineD3DDeviceImpl_SetMaterial,
7763     IWineD3DDeviceImpl_GetMaterial,
7764     IWineD3DDeviceImpl_SetNPatchMode,
7765     IWineD3DDeviceImpl_GetNPatchMode,
7766     IWineD3DDeviceImpl_SetPaletteEntries,
7767     IWineD3DDeviceImpl_GetPaletteEntries,
7768     IWineD3DDeviceImpl_SetPixelShader,
7769     IWineD3DDeviceImpl_GetPixelShader,
7770     IWineD3DDeviceImpl_SetPixelShaderConstantB,
7771     IWineD3DDeviceImpl_GetPixelShaderConstantB,
7772     IWineD3DDeviceImpl_SetPixelShaderConstantI,
7773     IWineD3DDeviceImpl_GetPixelShaderConstantI,
7774     IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst,
7775     IWineD3DDeviceImpl_GetPixelShaderConstantF,
7776     IWineD3DDeviceImpl_SetRenderState,
7777     IWineD3DDeviceImpl_GetRenderState,
7778     IWineD3DDeviceImpl_SetRenderTarget,
7779     IWineD3DDeviceImpl_GetRenderTarget,
7780     IWineD3DDeviceImpl_SetFrontBackBuffers,
7781     IWineD3DDeviceImpl_SetSamplerState,
7782     IWineD3DDeviceImpl_GetSamplerState,
7783     IWineD3DDeviceImpl_SetScissorRect,
7784     IWineD3DDeviceImpl_GetScissorRect,
7785     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7786     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7787     IWineD3DDeviceImpl_SetStreamSource,
7788     IWineD3DDeviceImpl_GetStreamSource,
7789     IWineD3DDeviceImpl_SetStreamSourceFreq,
7790     IWineD3DDeviceImpl_GetStreamSourceFreq,
7791     IWineD3DDeviceImpl_SetTexture,
7792     IWineD3DDeviceImpl_GetTexture,
7793     IWineD3DDeviceImpl_SetTextureStageState,
7794     IWineD3DDeviceImpl_GetTextureStageState,
7795     IWineD3DDeviceImpl_SetTransform,
7796     IWineD3DDeviceImpl_GetTransform,
7797     IWineD3DDeviceImpl_SetVertexDeclaration,
7798     IWineD3DDeviceImpl_GetVertexDeclaration,
7799     IWineD3DDeviceImpl_SetVertexShader,
7800     IWineD3DDeviceImpl_GetVertexShader,
7801     IWineD3DDeviceImpl_SetVertexShaderConstantB,
7802     IWineD3DDeviceImpl_GetVertexShaderConstantB,
7803     IWineD3DDeviceImpl_SetVertexShaderConstantI,
7804     IWineD3DDeviceImpl_GetVertexShaderConstantI,
7805     IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst,
7806     IWineD3DDeviceImpl_GetVertexShaderConstantF,
7807     IWineD3DDeviceImpl_SetViewport,
7808     IWineD3DDeviceImpl_GetViewport,
7809     IWineD3DDeviceImpl_MultiplyTransform,
7810     IWineD3DDeviceImpl_ValidateDevice,
7811     IWineD3DDeviceImpl_ProcessVertices,
7812     /*** State block ***/
7813     IWineD3DDeviceImpl_BeginStateBlock,
7814     IWineD3DDeviceImpl_EndStateBlock,
7815     /*** Scene management ***/
7816     IWineD3DDeviceImpl_BeginScene,
7817     IWineD3DDeviceImpl_EndScene,
7818     IWineD3DDeviceImpl_Present,
7819     IWineD3DDeviceImpl_Clear,
7820     /*** Drawing ***/
7821     IWineD3DDeviceImpl_DrawPrimitive,
7822     IWineD3DDeviceImpl_DrawIndexedPrimitive,
7823     IWineD3DDeviceImpl_DrawPrimitiveUP,
7824     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7825     IWineD3DDeviceImpl_DrawPrimitiveStrided,
7826     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
7827     IWineD3DDeviceImpl_DrawRectPatch,
7828     IWineD3DDeviceImpl_DrawTriPatch,
7829     IWineD3DDeviceImpl_DeletePatch,
7830     IWineD3DDeviceImpl_ColorFill,
7831     IWineD3DDeviceImpl_UpdateTexture,
7832     IWineD3DDeviceImpl_UpdateSurface,
7833     IWineD3DDeviceImpl_GetFrontBufferData,
7834     /*** object tracking ***/
7835     IWineD3DDeviceImpl_ResourceReleased,
7836     IWineD3DDeviceImpl_EnumResources
7837 };
7838
7839 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7840     WINED3DRS_ALPHABLENDENABLE   ,
7841     WINED3DRS_ALPHAFUNC          ,
7842     WINED3DRS_ALPHAREF           ,
7843     WINED3DRS_ALPHATESTENABLE    ,
7844     WINED3DRS_BLENDOP            ,
7845     WINED3DRS_COLORWRITEENABLE   ,
7846     WINED3DRS_DESTBLEND          ,
7847     WINED3DRS_DITHERENABLE       ,
7848     WINED3DRS_FILLMODE           ,
7849     WINED3DRS_FOGDENSITY         ,
7850     WINED3DRS_FOGEND             ,
7851     WINED3DRS_FOGSTART           ,
7852     WINED3DRS_LASTPIXEL          ,
7853     WINED3DRS_SHADEMODE          ,
7854     WINED3DRS_SRCBLEND           ,
7855     WINED3DRS_STENCILENABLE      ,
7856     WINED3DRS_STENCILFAIL        ,
7857     WINED3DRS_STENCILFUNC        ,
7858     WINED3DRS_STENCILMASK        ,
7859     WINED3DRS_STENCILPASS        ,
7860     WINED3DRS_STENCILREF         ,
7861     WINED3DRS_STENCILWRITEMASK   ,
7862     WINED3DRS_STENCILZFAIL       ,
7863     WINED3DRS_TEXTUREFACTOR      ,
7864     WINED3DRS_WRAP0              ,
7865     WINED3DRS_WRAP1              ,
7866     WINED3DRS_WRAP2              ,
7867     WINED3DRS_WRAP3              ,
7868     WINED3DRS_WRAP4              ,
7869     WINED3DRS_WRAP5              ,
7870     WINED3DRS_WRAP6              ,
7871     WINED3DRS_WRAP7              ,
7872     WINED3DRS_ZENABLE            ,
7873     WINED3DRS_ZFUNC              ,
7874     WINED3DRS_ZWRITEENABLE
7875 };
7876
7877 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7878     WINED3DTSS_ADDRESSW              ,
7879     WINED3DTSS_ALPHAARG0             ,
7880     WINED3DTSS_ALPHAARG1             ,
7881     WINED3DTSS_ALPHAARG2             ,
7882     WINED3DTSS_ALPHAOP               ,
7883     WINED3DTSS_BUMPENVLOFFSET        ,
7884     WINED3DTSS_BUMPENVLSCALE         ,
7885     WINED3DTSS_BUMPENVMAT00          ,
7886     WINED3DTSS_BUMPENVMAT01          ,
7887     WINED3DTSS_BUMPENVMAT10          ,
7888     WINED3DTSS_BUMPENVMAT11          ,
7889     WINED3DTSS_COLORARG0             ,
7890     WINED3DTSS_COLORARG1             ,
7891     WINED3DTSS_COLORARG2             ,
7892     WINED3DTSS_COLOROP               ,
7893     WINED3DTSS_RESULTARG             ,
7894     WINED3DTSS_TEXCOORDINDEX         ,
7895     WINED3DTSS_TEXTURETRANSFORMFLAGS
7896 };
7897
7898 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7899     WINED3DSAMP_ADDRESSU         ,
7900     WINED3DSAMP_ADDRESSV         ,
7901     WINED3DSAMP_ADDRESSW         ,
7902     WINED3DSAMP_BORDERCOLOR      ,
7903     WINED3DSAMP_MAGFILTER        ,
7904     WINED3DSAMP_MINFILTER        ,
7905     WINED3DSAMP_MIPFILTER        ,
7906     WINED3DSAMP_MIPMAPLODBIAS    ,
7907     WINED3DSAMP_MAXMIPLEVEL      ,
7908     WINED3DSAMP_MAXANISOTROPY    ,
7909     WINED3DSAMP_SRGBTEXTURE      ,
7910     WINED3DSAMP_ELEMENTINDEX
7911 };
7912
7913 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7914     WINED3DRS_AMBIENT                       ,
7915     WINED3DRS_AMBIENTMATERIALSOURCE         ,
7916     WINED3DRS_CLIPPING                      ,
7917     WINED3DRS_CLIPPLANEENABLE               ,
7918     WINED3DRS_COLORVERTEX                   ,
7919     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
7920     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
7921     WINED3DRS_FOGDENSITY                    ,
7922     WINED3DRS_FOGEND                        ,
7923     WINED3DRS_FOGSTART                      ,
7924     WINED3DRS_FOGTABLEMODE                  ,
7925     WINED3DRS_FOGVERTEXMODE                 ,
7926     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
7927     WINED3DRS_LIGHTING                      ,
7928     WINED3DRS_LOCALVIEWER                   ,
7929     WINED3DRS_MULTISAMPLEANTIALIAS          ,
7930     WINED3DRS_MULTISAMPLEMASK               ,
7931     WINED3DRS_NORMALIZENORMALS              ,
7932     WINED3DRS_PATCHEDGESTYLE                ,
7933     WINED3DRS_POINTSCALE_A                  ,
7934     WINED3DRS_POINTSCALE_B                  ,
7935     WINED3DRS_POINTSCALE_C                  ,
7936     WINED3DRS_POINTSCALEENABLE              ,
7937     WINED3DRS_POINTSIZE                     ,
7938     WINED3DRS_POINTSIZE_MAX                 ,
7939     WINED3DRS_POINTSIZE_MIN                 ,
7940     WINED3DRS_POINTSPRITEENABLE             ,
7941     WINED3DRS_RANGEFOGENABLE                ,
7942     WINED3DRS_SPECULARMATERIALSOURCE        ,
7943     WINED3DRS_TWEENFACTOR                   ,
7944     WINED3DRS_VERTEXBLEND                   ,
7945     WINED3DRS_CULLMODE                      ,
7946     WINED3DRS_FOGCOLOR
7947 };
7948
7949 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7950     WINED3DTSS_TEXCOORDINDEX         ,
7951     WINED3DTSS_TEXTURETRANSFORMFLAGS
7952 };
7953
7954 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7955     WINED3DSAMP_DMAPOFFSET
7956 };
7957
7958 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
7959     DWORD rep = This->shader_backend->StateTable[state].representative;
7960     DWORD idx;
7961     BYTE shift;
7962     UINT i;
7963     WineD3DContext *context;
7964
7965     if(!rep) return;
7966     for(i = 0; i < This->numContexts; i++) {
7967         context = This->contexts[i];
7968         if(isStateDirty(context, rep)) continue;
7969
7970         context->dirtyArray[context->numDirtyEntries++] = rep;
7971         idx = rep >> 5;
7972         shift = rep & 0x1f;
7973         context->isStateDirty[idx] |= (1 << shift);
7974     }
7975 }
7976
7977 void get_drawable_size_pbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7978     IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
7979     /* The drawable size of a pbuffer render target is the current pbuffer size
7980      */
7981     *width = dev->pbufferWidth;
7982     *height = dev->pbufferHeight;
7983 }
7984
7985 void get_drawable_size_fbo(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7986     /* The drawable size of a fbo target is the opengl texture size, which is the power of two size
7987      */
7988     *width = This->pow2Width;
7989     *height = This->pow2Height;
7990 }
7991
7992 void get_drawable_size_backbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7993     IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
7994     /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
7995      * current context's drawable, which is the size of the back buffer of the swapchain
7996      * the active context belongs to. The back buffer of the swapchain is stored as the
7997      * surface the context belongs to.
7998      */
7999     *width = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Width;
8000     *height = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Height;
8001 }