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