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