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