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