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