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