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