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