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