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