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