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