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