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