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