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