ntdll: The FileMailslotSetInformation and FileCompletionInformation cases of NtSetInf...
[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
4804     /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
4805      * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
4806      * for the cleared parts, and the untouched parts.
4807      *
4808      * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
4809      * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
4810      * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
4811      * checking all this if the dest surface is in the drawable anyway.
4812      */
4813     if((Flags & WINED3DCLEAR_TARGET) && !(target->Flags & SFLAG_INDRAWABLE)) {
4814         while(1) {
4815             if(vp->X != 0 || vp->Y != 0 ||
4816                vp->Width < target->currentDesc.Width || vp->Height < target->currentDesc.Height) {
4817                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4818                 break;
4819             }
4820             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && (
4821                This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 ||
4822                This->stateBlock->scissorRect.right < target->currentDesc.Width ||
4823                This->stateBlock->scissorRect.bottom < target->currentDesc.Height)) {
4824                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4825                 break;
4826             }
4827             if(Count > 0 && pRects && (
4828                pRects[0].x1 > 0 || pRects[0].y1 > 0 ||
4829                pRects[0].x2 < target->currentDesc.Width ||
4830                pRects[0].y2 < target->currentDesc.Height)) {
4831                 IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL);
4832                 break;
4833             }
4834             break;
4835         }
4836     }
4837
4838     target->get_drawable_size(target, &drawable_width, &drawable_height);
4839
4840     ActivateContext(This, (IWineD3DSurface *) target, CTXUSAGE_CLEAR);
4841     ENTER_GL();
4842
4843     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4844         apply_fbo_state((IWineD3DDevice *) This);
4845     }
4846
4847     /* Only set the values up once, as they are not changing */
4848     if (Flags & WINED3DCLEAR_STENCIL) {
4849         glClearStencil(Stencil);
4850         checkGLcall("glClearStencil");
4851         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4852         glStencilMask(0xFFFFFFFF);
4853     }
4854
4855     if (Flags & WINED3DCLEAR_ZBUFFER) {
4856         glDepthMask(GL_TRUE);
4857         glClearDepth(Z);
4858         checkGLcall("glClearDepth");
4859         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4860         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4861     }
4862
4863     if (Flags & WINED3DCLEAR_TARGET) {
4864         TRACE("Clearing screen with glClear to color %x\n", Color);
4865         glClearColor(D3DCOLOR_R(Color),
4866                      D3DCOLOR_G(Color),
4867                      D3DCOLOR_B(Color),
4868                      D3DCOLOR_A(Color));
4869         checkGLcall("glClearColor");
4870
4871         /* Clear ALL colors! */
4872         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4873         glMask = glMask | GL_COLOR_BUFFER_BIT;
4874     }
4875
4876     vp_rect.left = vp->X;
4877     vp_rect.top = vp->Y;
4878     vp_rect.right = vp->X + vp->Width;
4879     vp_rect.bottom = vp->Y + vp->Height;
4880     if (!(Count > 0 && pRects)) {
4881         if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
4882             IntersectRect(&vp_rect, &vp_rect, &This->stateBlock->scissorRect);
4883         }
4884         if(This->render_offscreen) {
4885             glScissor(vp_rect.left, vp_rect.top,
4886                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
4887         } else {
4888             glScissor(vp_rect.left, drawable_height - vp_rect.bottom,
4889                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
4890         }
4891         checkGLcall("glScissor");
4892         glClear(glMask);
4893         checkGLcall("glClear");
4894     } else {
4895         /* Now process each rect in turn */
4896         for (i = 0; i < Count; i++) {
4897             /* Note gl uses lower left, width/height */
4898             IntersectRect((RECT *) &curRect, &vp_rect, (RECT *) &pRects[i]);
4899             if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
4900                 IntersectRect((RECT *) &curRect, (RECT *) &curRect, &This->stateBlock->scissorRect);
4901             }
4902             TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This,
4903                   pRects[i].x1, pRects[i].y1, pRects[i].x2, pRects[i].y2,
4904                   curRect.x1, (target->currentDesc.Height - curRect.y2),
4905                   curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
4906
4907             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4908              * The rectangle is not cleared, no error is returned, but further rectanlges are
4909              * still cleared if they are valid
4910              */
4911             if(curRect.x1 > curRect.x2 || curRect.y1 > curRect.y2) {
4912                 TRACE("Rectangle with negative dimensions, ignoring\n");
4913                 continue;
4914             }
4915
4916             if(This->render_offscreen) {
4917                 glScissor(curRect.x1, curRect.y1,
4918                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
4919             } else {
4920                 glScissor(curRect.x1, drawable_height - curRect.y2,
4921                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
4922             }
4923             checkGLcall("glScissor");
4924
4925             glClear(glMask);
4926             checkGLcall("glClear");
4927         }
4928     }
4929
4930     /* Restore the old values (why..?) */
4931     if (Flags & WINED3DCLEAR_STENCIL) {
4932         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4933     }
4934     if (Flags & WINED3DCLEAR_TARGET) {
4935         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
4936         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4937                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4938                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4939                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4940
4941         /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
4942          * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
4943          */
4944         IWineD3DSurface_ModifyLocation(This->lastActiveRenderTarget, SFLAG_INDRAWABLE, TRUE);
4945         /* TODO: Move the fbo logic into ModifyLocation() */
4946         if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4947             target->Flags |= SFLAG_INTEXTURE;
4948         }
4949     }
4950     LEAVE_GL();
4951
4952     return WINED3D_OK;
4953 }
4954
4955 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4956                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4957     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4958     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0];
4959
4960     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This,
4961           Count, pRects, Flags, Color, Z, Stencil);
4962
4963     if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
4964         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4965         /* TODO: What about depth stencil buffers without stencil bits? */
4966         return WINED3DERR_INVALIDCALL;
4967     }
4968
4969     return IWineD3DDeviceImpl_ClearSurface(This, target, Count, pRects, Flags, Color, Z, Stencil);
4970 }
4971
4972 /*****
4973  * Drawing functions
4974  *****/
4975 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4976                                                 UINT PrimitiveCount) {
4977
4978     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4979
4980     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4981                                debug_d3dprimitivetype(PrimitiveType),
4982                                StartVertex, PrimitiveCount);
4983
4984     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4985     if(This->stateBlock->streamIsUP) {
4986         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4987         This->stateBlock->streamIsUP = FALSE;
4988     }
4989
4990     if(This->stateBlock->loadBaseVertexIndex != 0) {
4991         This->stateBlock->loadBaseVertexIndex = 0;
4992         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4993     }
4994     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4995     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4996                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4997     return WINED3D_OK;
4998 }
4999
5000 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5001 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
5002                                                            WINED3DPRIMITIVETYPE PrimitiveType,
5003                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
5004
5005     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
5006     UINT                 idxStride = 2;
5007     IWineD3DIndexBuffer *pIB;
5008     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
5009     GLuint vbo;
5010
5011     pIB = This->stateBlock->pIndexData;
5012     if (!pIB) {
5013         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
5014          * without an index buffer set. (The first time at least...)
5015          * D3D8 simply dies, but I doubt it can do much harm to return
5016          * D3DERR_INVALIDCALL there as well. */
5017         ERR("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
5018         return WINED3DERR_INVALIDCALL;
5019     }
5020
5021     if(This->stateBlock->streamIsUP) {
5022         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5023         This->stateBlock->streamIsUP = FALSE;
5024     }
5025     vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
5026
5027     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
5028           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5029           minIndex, NumVertices, startIndex, primCount);
5030
5031     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
5032     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
5033         idxStride = 2;
5034     } else {
5035         idxStride = 4;
5036     }
5037
5038     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
5039         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
5040         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5041     }
5042
5043     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
5044                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
5045
5046     return WINED3D_OK;
5047 }
5048
5049 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5050                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
5051                                                     UINT VertexStreamZeroStride) {
5052     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5053     IWineD3DVertexBuffer *vb;
5054
5055     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
5056              debug_d3dprimitivetype(PrimitiveType),
5057              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
5058
5059     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5060     vb = This->stateBlock->streamSource[0];
5061     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5062     if(vb) IWineD3DVertexBuffer_Release(vb);
5063     This->stateBlock->streamOffset[0] = 0;
5064     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5065     This->stateBlock->streamIsUP = TRUE;
5066     This->stateBlock->loadBaseVertexIndex = 0;
5067
5068     /* TODO: Only mark dirty if drawing from a different UP address */
5069     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
5070
5071     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
5072                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
5073
5074     /* MSDN specifies stream zero settings must be set to NULL */
5075     This->stateBlock->streamStride[0] = 0;
5076     This->stateBlock->streamSource[0] = NULL;
5077
5078     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
5079      * the new stream sources or use UP drawing again
5080      */
5081     return WINED3D_OK;
5082 }
5083
5084 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
5085                                                              UINT MinVertexIndex, UINT NumVertices,
5086                                                              UINT PrimitiveCount, CONST void* pIndexData,
5087                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
5088                                                              UINT VertexStreamZeroStride) {
5089     int                 idxStride;
5090     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5091     IWineD3DVertexBuffer *vb;
5092     IWineD3DIndexBuffer *ib;
5093
5094     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5095              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
5096              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
5097              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
5098
5099     if (IndexDataFormat == WINED3DFMT_INDEX16) {
5100         idxStride = 2;
5101     } else {
5102         idxStride = 4;
5103     }
5104
5105     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5106     vb = This->stateBlock->streamSource[0];
5107     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
5108     if(vb) IWineD3DVertexBuffer_Release(vb);
5109     This->stateBlock->streamIsUP = TRUE;
5110     This->stateBlock->streamOffset[0] = 0;
5111     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
5112
5113     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
5114     This->stateBlock->baseVertexIndex = 0;
5115     This->stateBlock->loadBaseVertexIndex = 0;
5116     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
5117     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5118     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5119
5120     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
5121
5122     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5123     This->stateBlock->streamSource[0] = NULL;
5124     This->stateBlock->streamStride[0] = 0;
5125     ib = This->stateBlock->pIndexData;
5126     if(ib) {
5127         IWineD3DIndexBuffer_Release(ib);
5128         This->stateBlock->pIndexData = NULL;
5129     }
5130     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
5131      * SetStreamSource to specify a vertex buffer
5132      */
5133
5134     return WINED3D_OK;
5135 }
5136
5137 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
5138     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5139
5140     /* Mark the state dirty until we have nicer tracking
5141      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5142      * that value.
5143      */
5144     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5145     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5146     This->stateBlock->baseVertexIndex = 0;
5147     This->up_strided = DrawPrimStrideData;
5148     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
5149     This->up_strided = NULL;
5150     return WINED3D_OK;
5151 }
5152
5153 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData, UINT NumVertices, CONST void *pIndexData, WINED3DFORMAT IndexDataFormat) {
5154     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5155     DWORD idxSize = (IndexDataFormat == WINED3DFMT_INDEX32 ? 4 : 2);
5156
5157     /* Mark the state dirty until we have nicer tracking
5158      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5159      * that value.
5160      */
5161     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5162     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
5163     This->stateBlock->streamIsUP = TRUE;
5164     This->stateBlock->baseVertexIndex = 0;
5165     This->up_strided = DrawPrimStrideData;
5166     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* startvertexidx */, 0 /* numindices */, 0 /* startidx */, idxSize, pIndexData, 0 /* minindex */);
5167     This->up_strided = NULL;
5168     return WINED3D_OK;
5169 }
5170
5171 static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface, IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume) {
5172     /* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
5173      * not callable by the app directly no parameter validation checks are needed here.
5174      */
5175     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5176     WINED3DLOCKED_BOX src;
5177     WINED3DLOCKED_BOX dst;
5178     HRESULT hr;
5179     TRACE("(%p)->(%p, %p)\n", This, pSourceVolume, pDestinationVolume);
5180
5181     /* TODO: Implement direct loading into the gl volume instead of using memcpy and
5182      * dirtification to improve loading performance.
5183      */
5184     hr = IWineD3DVolume_LockBox(pSourceVolume, &src, NULL, WINED3DLOCK_READONLY);
5185     if(FAILED(hr)) return hr;
5186     hr = IWineD3DVolume_LockBox(pDestinationVolume, &dst, NULL, WINED3DLOCK_DISCARD);
5187     if(FAILED(hr)) {
5188     IWineD3DVolume_UnlockBox(pSourceVolume);
5189             return hr;
5190     }
5191
5192     memcpy(dst.pBits, src.pBits, ((IWineD3DVolumeImpl *) pDestinationVolume)->resource.size);
5193
5194     hr = IWineD3DVolume_UnlockBox(pDestinationVolume);
5195     if(FAILED(hr)) {
5196         IWineD3DVolume_UnlockBox(pSourceVolume);
5197     } else {
5198         hr = IWineD3DVolume_UnlockBox(pSourceVolume);
5199     }
5200     return hr;
5201 }
5202
5203 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5204 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
5205     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5206     HRESULT hr = WINED3D_OK;
5207     WINED3DRESOURCETYPE sourceType;
5208     WINED3DRESOURCETYPE destinationType;
5209     int i ,levels;
5210
5211     /* TODO: think about moving the code into IWineD3DBaseTexture  */
5212
5213     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
5214
5215     /* verify that the source and destination textures aren't NULL */
5216     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
5217         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5218              This, pSourceTexture, pDestinationTexture);
5219         hr = WINED3DERR_INVALIDCALL;
5220     }
5221
5222     if (pSourceTexture == pDestinationTexture) {
5223         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5224              This, pSourceTexture, pDestinationTexture);
5225         hr = WINED3DERR_INVALIDCALL;
5226     }
5227     /* Verify that the source and destination textures are the same type */
5228     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
5229     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
5230
5231     if (sourceType != destinationType) {
5232         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5233              This);
5234         hr = WINED3DERR_INVALIDCALL;
5235     }
5236
5237     /* check that both textures have the identical numbers of levels  */
5238     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
5239         WARN("(%p) : source (%p) and destination (%p) textures must have identical numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
5240         hr = WINED3DERR_INVALIDCALL;
5241     }
5242
5243     if (WINED3D_OK == hr) {
5244
5245         /* Make sure that the destination texture is loaded */
5246         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
5247
5248         /* Update every surface level of the texture */
5249         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
5250
5251         switch (sourceType) {
5252         case WINED3DRTYPE_TEXTURE:
5253             {
5254                 IWineD3DSurface *srcSurface;
5255                 IWineD3DSurface *destSurface;
5256
5257                 for (i = 0 ; i < levels ; ++i) {
5258                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
5259                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
5260                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5261                     IWineD3DSurface_Release(srcSurface);
5262                     IWineD3DSurface_Release(destSurface);
5263                     if (WINED3D_OK != hr) {
5264                         WARN("(%p) : Call to update surface failed\n", This);
5265                         return hr;
5266                     }
5267                 }
5268             }
5269             break;
5270         case WINED3DRTYPE_CUBETEXTURE:
5271             {
5272                 IWineD3DSurface *srcSurface;
5273                 IWineD3DSurface *destSurface;
5274                 WINED3DCUBEMAP_FACES faceType;
5275
5276                 for (i = 0 ; i < levels ; ++i) {
5277                     /* Update each cube face */
5278                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
5279                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
5280                         if (WINED3D_OK != hr) {
5281                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5282                         } else {
5283                             TRACE("Got srcSurface %p\n", srcSurface);
5284                         }
5285                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
5286                         if (WINED3D_OK != hr) {
5287                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
5288                         } else {
5289                             TRACE("Got desrSurface %p\n", destSurface);
5290                         }
5291                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
5292                         IWineD3DSurface_Release(srcSurface);
5293                         IWineD3DSurface_Release(destSurface);
5294                         if (WINED3D_OK != hr) {
5295                             WARN("(%p) : Call to update surface failed\n", This);
5296                             return hr;
5297                         }
5298                     }
5299                 }
5300             }
5301             break;
5302
5303         case WINED3DRTYPE_VOLUMETEXTURE:
5304             {
5305                 IWineD3DVolume  *srcVolume  = NULL;
5306                 IWineD3DVolume  *destVolume = NULL;
5307
5308                 for (i = 0 ; i < levels ; ++i) {
5309                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
5310                     IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
5311                     hr =  IWineD3DDeviceImpl_UpdateVolume(iface, srcVolume, destVolume);
5312                     IWineD3DVolume_Release(srcVolume);
5313                     IWineD3DVolume_Release(destVolume);
5314                     if (WINED3D_OK != hr) {
5315                         WARN("(%p) : Call to update volume failed\n", This);
5316                         return hr;
5317                     }
5318                 }
5319             }
5320             break;
5321
5322         default:
5323             FIXME("(%p) : Unsupported source and destination type\n", This);
5324             hr = WINED3DERR_INVALIDCALL;
5325         }
5326     }
5327
5328     return hr;
5329 }
5330
5331 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5332     IWineD3DSwapChain *swapChain;
5333     HRESULT hr;
5334     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5335     if(hr == WINED3D_OK) {
5336         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5337                 IWineD3DSwapChain_Release(swapChain);
5338     }
5339     return hr;
5340 }
5341
5342 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5343     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5344     /* return a sensible default */
5345     *pNumPasses = 1;
5346     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5347     FIXME("(%p) : stub\n", This);
5348     return WINED3D_OK;
5349 }
5350
5351 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5352     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5353     int j;
5354     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5355     if (PaletteNumber >= MAX_PALETTES) {
5356         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5357         return WINED3DERR_INVALIDCALL;
5358     }
5359     for (j = 0; j < 256; ++j) {
5360         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5361         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5362         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5363         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5364     }
5365     TRACE("(%p) : returning\n", This);
5366     return WINED3D_OK;
5367 }
5368
5369 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5370     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5371     int j;
5372     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5373     if (PaletteNumber >= MAX_PALETTES) {
5374         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5375         return WINED3DERR_INVALIDCALL;
5376     }
5377     for (j = 0; j < 256; ++j) {
5378         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5379         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5380         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5381         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5382     }
5383     TRACE("(%p) : returning\n", This);
5384     return WINED3D_OK;
5385 }
5386
5387 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5388     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5389     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5390     if (PaletteNumber >= MAX_PALETTES) {
5391         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5392         return WINED3DERR_INVALIDCALL;
5393     }
5394     /*TODO: stateblocks */
5395     This->currentPalette = PaletteNumber;
5396     TRACE("(%p) : returning\n", This);
5397     return WINED3D_OK;
5398 }
5399
5400 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5401     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5402     if (PaletteNumber == NULL) {
5403         WARN("(%p) : returning Invalid Call\n", This);
5404         return WINED3DERR_INVALIDCALL;
5405     }
5406     /*TODO: stateblocks */
5407     *PaletteNumber = This->currentPalette;
5408     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5409     return WINED3D_OK;
5410 }
5411
5412 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5413     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5414     static BOOL showFixmes = TRUE;
5415     if (showFixmes) {
5416         FIXME("(%p) : stub\n", This);
5417         showFixmes = FALSE;
5418     }
5419
5420     This->softwareVertexProcessing = bSoftware;
5421     return WINED3D_OK;
5422 }
5423
5424
5425 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5426     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5427     static BOOL showFixmes = TRUE;
5428     if (showFixmes) {
5429         FIXME("(%p) : stub\n", This);
5430         showFixmes = FALSE;
5431     }
5432     return This->softwareVertexProcessing;
5433 }
5434
5435
5436 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5437     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5438     IWineD3DSwapChain *swapChain;
5439     HRESULT hr;
5440
5441     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5442
5443     hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
5444     if(hr == WINED3D_OK){
5445         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5446         IWineD3DSwapChain_Release(swapChain);
5447     }else{
5448         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5449     }
5450     return hr;
5451 }
5452
5453
5454 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5455     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5456     static BOOL showfixmes = TRUE;
5457     if(nSegments != 0.0f) {
5458         if( showfixmes) {
5459             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5460             showfixmes = FALSE;
5461         }
5462     }
5463     return WINED3D_OK;
5464 }
5465
5466 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5467     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5468     static BOOL showfixmes = TRUE;
5469     if( showfixmes) {
5470         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5471         showfixmes = FALSE;
5472     }
5473     return 0.0f;
5474 }
5475
5476 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5477     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5478     /** TODO: remove casts to IWineD3DSurfaceImpl
5479      *       NOTE: move code to surface to accomplish this
5480       ****************************************/
5481     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5482     int srcWidth, srcHeight;
5483     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5484     WINED3DFORMAT destFormat, srcFormat;
5485     UINT          destSize;
5486     int srcLeft, destLeft, destTop;
5487     WINED3DPOOL       srcPool, destPool;
5488     int offset    = 0;
5489     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5490     glDescriptor *glDescription = NULL;
5491     GLenum dummy;
5492     int bpp;
5493     CONVERT_TYPES convert = NO_CONVERSION;
5494
5495     WINED3DSURFACE_DESC  winedesc;
5496
5497     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5498     memset(&winedesc, 0, sizeof(winedesc));
5499     winedesc.Width  = &srcSurfaceWidth;
5500     winedesc.Height = &srcSurfaceHeight;
5501     winedesc.Pool   = &srcPool;
5502     winedesc.Format = &srcFormat;
5503
5504     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5505
5506     winedesc.Width  = &destSurfaceWidth;
5507     winedesc.Height = &destSurfaceHeight;
5508     winedesc.Pool   = &destPool;
5509     winedesc.Format = &destFormat;
5510     winedesc.Size   = &destSize;
5511
5512     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5513
5514     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5515         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5516         return WINED3DERR_INVALIDCALL;
5517     }
5518
5519     /* This call loads the opengl surface directly, instead of copying the surface to the
5520      * destination's sysmem copy. If surface conversion is needed, use BltFast instead to
5521      * copy in sysmem and use regular surface loading.
5522      */
5523     d3dfmt_get_conv((IWineD3DSurfaceImpl *) pDestinationSurface, FALSE, TRUE,
5524                     &dummy, &dummy, &dummy, &convert, &bpp, FALSE);
5525     if(convert != NO_CONVERSION) {
5526         return IWineD3DSurface_BltFast(pDestinationSurface,
5527                                         pDestPoint  ? pDestPoint->x : 0,
5528                                         pDestPoint  ? pDestPoint->y : 0,
5529                                         pSourceSurface, (RECT *) pSourceRect, 0);
5530     }
5531
5532     if (destFormat == WINED3DFMT_UNKNOWN) {
5533         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5534         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5535
5536         /* Get the update surface description */
5537         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5538     }
5539
5540     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5541
5542     ENTER_GL();
5543
5544     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
5545         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5546         checkGLcall("glActiveTextureARB");
5547     }
5548
5549     /* Make sure the surface is loaded and up to date */
5550     IWineD3DSurface_PreLoad(pDestinationSurface);
5551
5552     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5553
5554     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5555     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5556     srcHeight  = pSourceRect ? pSourceRect->bottom - pSourceRect->top   : srcSurfaceHeight;
5557     srcLeft    = pSourceRect ? pSourceRect->left : 0;
5558     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5559     destTop    = pDestPoint  ? pDestPoint->y : 0;
5560
5561
5562     /* This function doesn't support compressed textures
5563     the pitch is just bytesPerPixel * width */
5564     if(srcWidth != srcSurfaceWidth  || srcLeft ){
5565         rowoffset = srcSurfaceWidth * pSrcSurface->bytesPerPixel;
5566         offset   += srcLeft * pSrcSurface->bytesPerPixel;
5567         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5568     }
5569     /* TODO DXT formats */
5570
5571     if(pSourceRect != NULL && pSourceRect->top != 0){
5572        offset +=  pSourceRect->top * srcSurfaceWidth * pSrcSurface->bytesPerPixel;
5573     }
5574     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5575     ,This
5576     ,glDescription->level
5577     ,destLeft
5578     ,destTop
5579     ,srcWidth
5580     ,srcHeight
5581     ,glDescription->glFormat
5582     ,glDescription->glType
5583     ,IWineD3DSurface_GetData(pSourceSurface)
5584     );
5585
5586     /* Sanity check */
5587     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5588
5589         /* need to lock the surface to get the data */
5590         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5591     }
5592
5593     /* TODO: Cube and volume support */
5594     if(rowoffset != 0){
5595         /* not a whole row so we have to do it a line at a time */
5596         int j;
5597
5598         /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */
5599         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5600
5601         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5602
5603                 glTexSubImage2D(glDescription->target
5604                     ,glDescription->level
5605                     ,destLeft
5606                     ,j
5607                     ,srcWidth
5608                     ,1
5609                     ,glDescription->glFormat
5610                     ,glDescription->glType
5611                     ,data /* could be quicker using */
5612                 );
5613             data += rowoffset;
5614         }
5615
5616     } else { /* Full width, so just write out the whole texture */
5617
5618         if (WINED3DFMT_DXT1 == destFormat ||
5619             WINED3DFMT_DXT2 == destFormat ||
5620             WINED3DFMT_DXT3 == destFormat ||
5621             WINED3DFMT_DXT4 == destFormat ||
5622             WINED3DFMT_DXT5 == destFormat) {
5623             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5624                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5625                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5626                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5627                 } if (destFormat != srcFormat) {
5628                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5629                 } else {
5630                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5631                                                         glDescription->level,
5632                                                         glDescription->glFormatInternal,
5633                                                         srcWidth,
5634                                                         srcHeight,
5635                                                         0,
5636                                                         destSize,
5637                                                         IWineD3DSurface_GetData(pSourceSurface));
5638                 }
5639             } else {
5640                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5641             }
5642
5643
5644         } else {
5645             glTexSubImage2D(glDescription->target
5646                     ,glDescription->level
5647                     ,destLeft
5648                     ,destTop
5649                     ,srcWidth
5650                     ,srcHeight
5651                     ,glDescription->glFormat
5652                     ,glDescription->glType
5653                     ,IWineD3DSurface_GetData(pSourceSurface)
5654                 );
5655         }
5656      }
5657     checkGLcall("glTexSubImage2D");
5658
5659     LEAVE_GL();
5660
5661     IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE);
5662     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
5663
5664     return WINED3D_OK;
5665 }
5666
5667 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5668     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5669     struct WineD3DRectPatch *patch;
5670     unsigned int i;
5671     struct list *e;
5672     BOOL found;
5673     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5674
5675     if(!(Handle || pRectPatchInfo)) {
5676         /* TODO: Write a test for the return value, thus the FIXME */
5677         FIXME("Both Handle and pRectPatchInfo are NULL\n");
5678         return WINED3DERR_INVALIDCALL;
5679     }
5680
5681     if(Handle) {
5682         i = PATCHMAP_HASHFUNC(Handle);
5683         found = FALSE;
5684         LIST_FOR_EACH(e, &This->patches[i]) {
5685             patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5686             if(patch->Handle == Handle) {
5687                 found = TRUE;
5688                 break;
5689             }
5690         }
5691
5692         if(!found) {
5693             TRACE("Patch does not exist. Creating a new one\n");
5694             patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5695             patch->Handle = Handle;
5696             list_add_head(&This->patches[i], &patch->entry);
5697         } else {
5698             TRACE("Found existing patch %p\n", patch);
5699         }
5700     } else {
5701         /* Since opengl does not load tesselated vertex attributes into numbered vertex
5702          * attributes we have to tesselate, read back, and draw. This needs a patch
5703          * management structure instance. Create one.
5704          *
5705          * A possible improvement is to check if a vertex shader is used, and if not directly
5706          * draw the patch.
5707          */
5708         FIXME("Drawing an uncached patch. This is slow\n");
5709         patch = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*patch));
5710     }
5711
5712     if(pNumSegs[0] != patch->numSegs[0] || pNumSegs[1] != patch->numSegs[1] ||
5713        pNumSegs[2] != patch->numSegs[2] || pNumSegs[3] != patch->numSegs[3] ||
5714        (pRectPatchInfo && memcmp(pRectPatchInfo, &patch->RectPatchInfo, sizeof(*pRectPatchInfo)) != 0) ) {
5715         HRESULT hr;
5716         TRACE("Tesselation density or patch info changed, retesselating\n");
5717
5718         if(pRectPatchInfo) {
5719             memcpy(&patch->RectPatchInfo, pRectPatchInfo, sizeof(*pRectPatchInfo));
5720         }
5721         patch->numSegs[0] = pNumSegs[0];
5722         patch->numSegs[1] = pNumSegs[1];
5723         patch->numSegs[2] = pNumSegs[2];
5724         patch->numSegs[3] = pNumSegs[3];
5725
5726         hr = tesselate_rectpatch(This, patch);
5727         if(FAILED(hr)) {
5728             WARN("Patch tesselation failed\n");
5729
5730             /* Do not release the handle to store the params of the patch */
5731             if(!Handle) {
5732                 HeapFree(GetProcessHeap(), 0, patch);
5733             }
5734             return hr;
5735         }
5736     }
5737
5738     This->currentPatch = patch;
5739     IWineD3DDevice_DrawPrimitiveStrided(iface, WINED3DPT_TRIANGLELIST, patch->numSegs[0] * patch->numSegs[1] * 2, &patch->strided);
5740     This->currentPatch = NULL;
5741
5742     /* Destroy uncached patches */
5743     if(!Handle) {
5744         HeapFree(GetProcessHeap(), 0, patch->mem);
5745         HeapFree(GetProcessHeap(), 0, patch);
5746     }
5747     return WINED3D_OK;
5748 }
5749
5750 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5751 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5752     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5753     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5754     FIXME("(%p) : Stub\n", This);
5755     return WINED3D_OK;
5756 }
5757
5758 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5759     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5760     int i;
5761     struct WineD3DRectPatch *patch;
5762     struct list *e;
5763     TRACE("(%p) Handle(%d)\n", This, Handle);
5764
5765     i = PATCHMAP_HASHFUNC(Handle);
5766     LIST_FOR_EACH(e, &This->patches[i]) {
5767         patch = LIST_ENTRY(e, struct WineD3DRectPatch, entry);
5768         if(patch->Handle == Handle) {
5769             TRACE("Deleting patch %p\n", patch);
5770             list_remove(&patch->entry);
5771             HeapFree(GetProcessHeap(), 0, patch->mem);
5772             HeapFree(GetProcessHeap(), 0, patch);
5773             return WINED3D_OK;
5774         }
5775     }
5776
5777     /* TODO: Write a test for the return value */
5778     FIXME("Attempt to destroy nonexistent patch\n");
5779     return WINED3DERR_INVALIDCALL;
5780 }
5781
5782 static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) {
5783     HRESULT hr;
5784     IWineD3DSwapChain *swapchain;
5785
5786     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain);
5787     if (SUCCEEDED(hr)) {
5788         IWineD3DSwapChain_Release((IUnknown *)swapchain);
5789         return swapchain;
5790     }
5791
5792     return NULL;
5793 }
5794
5795 static void bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) {
5796     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5797
5798     if (!*fbo) {
5799         GL_EXTCALL(glGenFramebuffersEXT(1, fbo));
5800         checkGLcall("glGenFramebuffersEXT()");
5801     }
5802     GL_EXTCALL(glBindFramebufferEXT(target, *fbo));
5803     checkGLcall("glBindFramebuffer()");
5804 }
5805
5806 static void attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) {
5807     const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface;
5808     IWineD3DBaseTextureImpl *texture_impl;
5809     GLenum texttarget, target;
5810     GLint old_binding;
5811
5812     texttarget = surface_impl->glDescription.target;
5813     if(texttarget == GL_TEXTURE_2D) {
5814         target = GL_TEXTURE_2D;
5815         glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
5816     } else if(texttarget == GL_TEXTURE_RECTANGLE_ARB) {
5817         target = GL_TEXTURE_RECTANGLE_ARB;
5818         glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
5819     } else {
5820         target = GL_TEXTURE_CUBE_MAP_ARB;
5821         glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5822     }
5823
5824     IWineD3DSurface_PreLoad(surface);
5825
5826     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5827     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5828     glBindTexture(target, old_binding);
5829
5830     /* Update base texture states array */
5831     if (SUCCEEDED(IWineD3DSurface_GetContainer(surface, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
5832         texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
5833         texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
5834         if (texture_impl->baseTexture.bindCount) {
5835             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
5836         }
5837
5838         IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
5839     }
5840
5841     GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget,
5842             surface_impl->glDescription.textureName, surface_impl->glDescription.level));
5843
5844     checkGLcall("attach_surface_fbo");
5845 }
5846
5847 static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONST WINED3DRECT *rect, WINED3DCOLOR color) {
5848     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5849     IWineD3DSwapChain *swapchain;
5850
5851     swapchain = get_swapchain(surface);
5852     if (swapchain) {
5853         GLenum buffer;
5854
5855         TRACE("Surface %p is onscreen\n", surface);
5856
5857         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5858         buffer = surface_get_gl_buffer(surface, swapchain);
5859         glDrawBuffer(buffer);
5860         checkGLcall("glDrawBuffer()");
5861     } else {
5862         TRACE("Surface %p is offscreen\n", surface);
5863         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->dst_fbo);
5864         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface);
5865     }
5866
5867     if (rect) {
5868         glEnable(GL_SCISSOR_TEST);
5869         if(!swapchain) {
5870             glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1);
5871         } else {
5872             glScissor(rect->x1, ((IWineD3DSurfaceImpl *)surface)->currentDesc.Height - rect->y2,
5873                     rect->x2 - rect->x1, rect->y2 - rect->y1);
5874         }
5875         checkGLcall("glScissor");
5876     } else {
5877         glDisable(GL_SCISSOR_TEST);
5878     }
5879     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
5880
5881     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5882     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
5883
5884     glClearColor(D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color));
5885     glClear(GL_COLOR_BUFFER_BIT);
5886     checkGLcall("glClear");
5887
5888     if (This->render_offscreen) {
5889         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5890     } else {
5891         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5892         checkGLcall("glBindFramebuffer()");
5893     }
5894
5895     if (swapchain && surface == ((IWineD3DSwapChainImpl *)swapchain)->frontBuffer
5896             && ((IWineD3DSwapChainImpl *)swapchain)->backBuffer) {
5897         glDrawBuffer(GL_BACK);
5898         checkGLcall("glDrawBuffer()");
5899     }
5900 }
5901
5902 static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) {
5903     unsigned int r, g, b, a;
5904     DWORD ret;
5905
5906     if(destfmt == WINED3DFMT_A8R8G8B8 || destfmt == WINED3DFMT_X8R8G8B8 ||
5907        destfmt == WINED3DFMT_R8G8B8)
5908         return color;
5909
5910     TRACE("Converting color %08x to format %s\n", color, debug_d3dformat(destfmt));
5911
5912     a = (color & 0xff000000) >> 24;
5913     r = (color & 0x00ff0000) >> 16;
5914     g = (color & 0x0000ff00) >>  8;
5915     b = (color & 0x000000ff) >>  0;
5916
5917     switch(destfmt)
5918     {
5919         case WINED3DFMT_R5G6B5:
5920             if(r == 0xff && g == 0xff && b == 0xff) return 0xffff;
5921             r = (r * 32) / 256;
5922             g = (g * 64) / 256;
5923             b = (b * 32) / 256;
5924             ret  = r << 11;
5925             ret |= g << 5;
5926             ret |= b;
5927             TRACE("Returning %08x\n", ret);
5928             return ret;
5929
5930         case WINED3DFMT_X1R5G5B5:
5931         case WINED3DFMT_A1R5G5B5:
5932             a = (a *  2) / 256;
5933             r = (r * 32) / 256;
5934             g = (g * 32) / 256;
5935             b = (b * 32) / 256;
5936             ret  = a << 15;
5937             ret |= r << 10;
5938             ret |= g <<  5;
5939             ret |= b <<  0;
5940             TRACE("Returning %08x\n", ret);
5941             return ret;
5942
5943         case WINED3DFMT_A8:
5944             TRACE("Returning %08x\n", a);
5945             return a;
5946
5947         case WINED3DFMT_X4R4G4B4:
5948         case WINED3DFMT_A4R4G4B4:
5949             a = (a * 16) / 256;
5950             r = (r * 16) / 256;
5951             g = (g * 16) / 256;
5952             b = (b * 16) / 256;
5953             ret  = a << 12;
5954             ret |= r <<  8;
5955             ret |= g <<  4;
5956             ret |= b <<  0;
5957             TRACE("Returning %08x\n", ret);
5958             return ret;
5959
5960         case WINED3DFMT_R3G3B2:
5961             r = (r * 8) / 256;
5962             g = (g * 8) / 256;
5963             b = (b * 4) / 256;
5964             ret  = r <<  5;
5965             ret |= g <<  2;
5966             ret |= b <<  0;
5967             TRACE("Returning %08x\n", ret);
5968             return ret;
5969
5970         case WINED3DFMT_X8B8G8R8:
5971         case WINED3DFMT_A8B8G8R8:
5972             ret  = a << 24;
5973             ret |= b << 16;
5974             ret |= g <<  8;
5975             ret |= r <<  0;
5976             TRACE("Returning %08x\n", ret);
5977             return ret;
5978
5979         case WINED3DFMT_A2R10G10B10:
5980             a = (a *    4) / 256;
5981             r = (r * 1024) / 256;
5982             g = (g * 1024) / 256;
5983             b = (b * 1024) / 256;
5984             ret  = a << 30;
5985             ret |= r << 20;
5986             ret |= g << 10;
5987             ret |= b <<  0;
5988             TRACE("Returning %08x\n", ret);
5989             return ret;
5990
5991         case WINED3DFMT_A2B10G10R10:
5992             a = (a *    4) / 256;
5993             r = (r * 1024) / 256;
5994             g = (g * 1024) / 256;
5995             b = (b * 1024) / 256;
5996             ret  = a << 30;
5997             ret |= b << 20;
5998             ret |= g << 10;
5999             ret |= r <<  0;
6000             TRACE("Returning %08x\n", ret);
6001             return ret;
6002
6003         default:
6004             FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt));
6005             return 0;
6006     }
6007 }
6008
6009 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
6010     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6011     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
6012     WINEDDBLTFX BltFx;
6013     TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This, pSurface, pRect, color);
6014
6015     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
6016         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6017         return WINED3DERR_INVALIDCALL;
6018     }
6019
6020     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
6021         color_fill_fbo(iface, pSurface, pRect, color);
6022         return WINED3D_OK;
6023     } else {
6024         /* Just forward this to the DirectDraw blitting engine */
6025         memset(&BltFx, 0, sizeof(BltFx));
6026         BltFx.dwSize = sizeof(BltFx);
6027         BltFx.u5.dwFillColor = argb_to_fmt(color, surface->resource.format);
6028         return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE);
6029     }
6030 }
6031
6032 /* rendertarget and depth stencil functions */
6033 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
6034     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6035
6036     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6037         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
6038         return WINED3DERR_INVALIDCALL;
6039     }
6040
6041     *ppRenderTarget = This->render_targets[RenderTargetIndex];
6042     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
6043     /* Note inc ref on returned surface */
6044     if(*ppRenderTarget != NULL)
6045         IWineD3DSurface_AddRef(*ppRenderTarget);
6046     return WINED3D_OK;
6047 }
6048
6049 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
6050     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6051     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
6052     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
6053     IWineD3DSwapChainImpl *Swapchain;
6054     HRESULT hr;
6055
6056     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
6057
6058     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
6059     if(hr != WINED3D_OK) {
6060         ERR("Can't get the swapchain\n");
6061         return hr;
6062     }
6063
6064     /* Make sure to release the swapchain */
6065     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
6066
6067     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
6068         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6069         return WINED3DERR_INVALIDCALL;
6070     }
6071     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6072         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6073         return WINED3DERR_INVALIDCALL;
6074     }
6075
6076     if(Swapchain->frontBuffer != Front) {
6077         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
6078
6079         if(Swapchain->frontBuffer)
6080             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
6081         Swapchain->frontBuffer = Front;
6082
6083         if(Swapchain->frontBuffer) {
6084             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
6085         }
6086     }
6087
6088     if(Back && !Swapchain->backBuffer) {
6089         /* We need memory for the back buffer array - only one back buffer this way */
6090         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
6091         if(!Swapchain->backBuffer) {
6092             ERR("Out of memory\n");
6093             return E_OUTOFMEMORY;
6094         }
6095     }
6096
6097     if(Swapchain->backBuffer[0] != Back) {
6098         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
6099
6100         /* What to do about the context here in the case of multithreading? Not sure.
6101          * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
6102          */
6103         ENTER_GL();
6104         if(!Swapchain->backBuffer[0]) {
6105             /* GL was told to draw to the front buffer at creation,
6106              * undo that
6107              */
6108             glDrawBuffer(GL_BACK);
6109             checkGLcall("glDrawBuffer(GL_BACK)");
6110             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6111             Swapchain->presentParms.BackBufferCount = 1;
6112         } else if (!Back) {
6113             /* That makes problems - disable for now */
6114             /* glDrawBuffer(GL_FRONT); */
6115             checkGLcall("glDrawBuffer(GL_FRONT)");
6116             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6117             Swapchain->presentParms.BackBufferCount = 0;
6118         }
6119         LEAVE_GL();
6120
6121         if(Swapchain->backBuffer[0])
6122             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
6123         Swapchain->backBuffer[0] = Back;
6124
6125         if(Swapchain->backBuffer[0]) {
6126             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
6127         } else {
6128             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
6129             Swapchain->backBuffer = NULL;
6130         }
6131
6132     }
6133
6134     return WINED3D_OK;
6135 }
6136
6137 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
6138     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6139     *ppZStencilSurface = This->stencilBufferTarget;
6140     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
6141
6142     if(*ppZStencilSurface != NULL) {
6143         /* Note inc ref on returned surface */
6144         IWineD3DSurface_AddRef(*ppZStencilSurface);
6145         return WINED3D_OK;
6146     } else {
6147         return WINED3DERR_NOTFOUND;
6148     }
6149 }
6150
6151 /* TODO: Handle stencil attachments */
6152 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
6153     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6154     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
6155
6156     TRACE("Set depth stencil to %p\n", depth_stencil);
6157
6158     if (depth_stencil_impl) {
6159         if (depth_stencil_impl->current_renderbuffer) {
6160             GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id));
6161             checkGLcall("glFramebufferRenderbufferEXT()");
6162         } else {
6163             IWineD3DBaseTextureImpl *texture_impl;
6164             GLenum texttarget, target;
6165             GLint old_binding = 0;
6166
6167             texttarget = depth_stencil_impl->glDescription.target;
6168             if(texttarget == GL_TEXTURE_2D) {
6169                 target = GL_TEXTURE_2D;
6170                 glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
6171             } else if(texttarget == GL_TEXTURE_RECTANGLE_ARB) {
6172                 target = GL_TEXTURE_RECTANGLE_ARB;
6173                 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
6174             } else {
6175                 target = GL_TEXTURE_CUBE_MAP_ARB;
6176                 glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
6177             }
6178
6179             IWineD3DSurface_PreLoad(depth_stencil);
6180
6181             glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6182             glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6183             glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
6184             glBindTexture(target, old_binding);
6185
6186             /* Update base texture states array */
6187             if (SUCCEEDED(IWineD3DSurface_GetContainer(depth_stencil, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
6188                 texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
6189                 texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
6190                 if (texture_impl->baseTexture.bindCount) {
6191                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
6192                 }
6193
6194                 IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
6195             }
6196
6197             GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget,
6198                     depth_stencil_impl->glDescription.textureName, depth_stencil_impl->glDescription.level));
6199             checkGLcall("glFramebufferTexture2DEXT()");
6200         }
6201     } else {
6202         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
6203         checkGLcall("glFramebufferTexture2DEXT()");
6204     }
6205 }
6206
6207 static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
6208     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6209     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
6210
6211     TRACE("Set render target %u to %p\n", idx, render_target);
6212
6213     if (rtimpl) {
6214         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, idx, render_target);
6215         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
6216     } else {
6217         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
6218         checkGLcall("glFramebufferTexture2DEXT()");
6219
6220         This->draw_buffers[idx] = GL_NONE;
6221     }
6222 }
6223
6224 static void check_fbo_status(IWineD3DDevice *iface) {
6225     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6226     GLenum status;
6227
6228     status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
6229     if (status == GL_FRAMEBUFFER_COMPLETE_EXT) {
6230         TRACE("FBO complete\n");
6231     } else {
6232         IWineD3DSurfaceImpl *attachment;
6233         int i;
6234         FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status);
6235
6236         /* Dump the FBO attachments */
6237         for (i = 0; i < GL_LIMITS(buffers); ++i) {
6238             attachment = (IWineD3DSurfaceImpl *)This->fbo_color_attachments[i];
6239             if (attachment) {
6240                 FIXME("\tColor attachment %d: (%p) %s %ux%u\n", i, attachment, debug_d3dformat(attachment->resource.format),
6241                         attachment->pow2Width, attachment->pow2Height);
6242             }
6243         }
6244         attachment = (IWineD3DSurfaceImpl *)This->fbo_depth_attachment;
6245         if (attachment) {
6246             FIXME("\tDepth attachment: (%p) %s %ux%u\n", attachment, debug_d3dformat(attachment->resource.format),
6247                     attachment->pow2Width, attachment->pow2Height);
6248         }
6249     }
6250 }
6251
6252 static BOOL depth_mismatch_fbo(IWineD3DDevice *iface) {
6253     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6254     IWineD3DSurfaceImpl *rt_impl = (IWineD3DSurfaceImpl *)This->render_targets[0];
6255     IWineD3DSurfaceImpl *ds_impl = (IWineD3DSurfaceImpl *)This->stencilBufferTarget;
6256
6257     if (!ds_impl) return FALSE;
6258
6259     if (ds_impl->current_renderbuffer) {
6260         return (rt_impl->pow2Width != ds_impl->current_renderbuffer->width ||
6261                 rt_impl->pow2Height != ds_impl->current_renderbuffer->height);
6262     }
6263
6264     return (rt_impl->pow2Width != ds_impl->pow2Width ||
6265             rt_impl->pow2Height != ds_impl->pow2Height);
6266 }
6267
6268 void apply_fbo_state(IWineD3DDevice *iface) {
6269     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6270     unsigned int i;
6271
6272     if (This->render_offscreen) {
6273         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6274
6275         /* Apply render targets */
6276         for (i = 0; i < GL_LIMITS(buffers); ++i) {
6277             IWineD3DSurface *render_target = This->render_targets[i];
6278             if (This->fbo_color_attachments[i] != render_target) {
6279                 set_render_target_fbo(iface, i, render_target);
6280                 This->fbo_color_attachments[i] = render_target;
6281             }
6282         }
6283
6284         /* Apply depth targets */
6285         if (This->fbo_depth_attachment != This->stencilBufferTarget || depth_mismatch_fbo(iface)) {
6286             unsigned int w = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Width;
6287             unsigned int h = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Height;
6288
6289             if (This->stencilBufferTarget) {
6290                 surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h);
6291             }
6292             set_depth_stencil_fbo(iface, This->stencilBufferTarget);
6293             This->fbo_depth_attachment = This->stencilBufferTarget;
6294         }
6295
6296         if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
6297             GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
6298             checkGLcall("glDrawBuffers()");
6299         } else {
6300             glDrawBuffer(This->draw_buffers[0]);
6301             checkGLcall("glDrawBuffer()");
6302         }
6303     } else {
6304         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6305     }
6306
6307     check_fbo_status(iface);
6308 }
6309
6310 void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect,
6311         IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) {
6312     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6313     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
6314     IWineD3DSwapChain *src_swapchain, *dst_swapchain;
6315     GLenum gl_filter;
6316
6317     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
6318             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
6319     TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2);
6320     TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2);
6321
6322     switch (filter) {
6323         case WINED3DTEXF_LINEAR:
6324             gl_filter = GL_LINEAR;
6325             break;
6326
6327         default:
6328             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
6329         case WINED3DTEXF_NONE:
6330         case WINED3DTEXF_POINT:
6331             gl_filter = GL_NEAREST;
6332             break;
6333     }
6334
6335     /* Attach src surface to src fbo */
6336     src_swapchain = get_swapchain(src_surface);
6337     if (src_swapchain) {
6338         GLenum buffer;
6339
6340         TRACE("Source surface %p is onscreen\n", src_surface);
6341         ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD);
6342         /* Make sure the drawable is up to date. In the offscreen case
6343          * attach_surface_fbo() implicitly takes care of this. */
6344         IWineD3DSurface_LoadLocation(src_surface, SFLAG_INDRAWABLE, NULL);
6345
6346         ENTER_GL();
6347         GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0));
6348         buffer = surface_get_gl_buffer(src_surface, src_swapchain);
6349         glReadBuffer(buffer);
6350         checkGLcall("glReadBuffer()");
6351
6352         src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
6353         src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
6354     } else {
6355         TRACE("Source surface %p is offscreen\n", src_surface);
6356         ENTER_GL();
6357         bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo);
6358         attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
6359         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
6360         checkGLcall("glReadBuffer()");
6361     }
6362     LEAVE_GL();
6363
6364     /* Attach dst surface to dst fbo */
6365     dst_swapchain = get_swapchain(dst_surface);
6366     if (dst_swapchain) {
6367         GLenum buffer;
6368
6369         TRACE("Destination surface %p is onscreen\n", dst_surface);
6370         ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD);
6371         /* Make sure the drawable is up to date. In the offscreen case
6372          * attach_surface_fbo() implicitly takes care of this. */
6373         IWineD3DSurface_LoadLocation(dst_surface, SFLAG_INDRAWABLE, NULL);
6374
6375         ENTER_GL();
6376         GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0));
6377         buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
6378         glDrawBuffer(buffer);
6379         checkGLcall("glDrawBuffer()");
6380
6381         dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
6382         dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
6383     } else {
6384         TRACE("Destination surface %p is offscreen\n", dst_surface);
6385
6386         /* No src or dst swapchain? Make sure some context is active(multithreading) */
6387         if(!src_swapchain) {
6388             ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6389         }
6390
6391         ENTER_GL();
6392         bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo);
6393         attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
6394         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
6395         checkGLcall("glDrawBuffer()");
6396     }
6397     glDisable(GL_SCISSOR_TEST);
6398     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
6399
6400     if (flip) {
6401         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6402                 dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter));
6403         checkGLcall("glBlitFramebuffer()");
6404     } else {
6405         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
6406                 dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter));
6407         checkGLcall("glBlitFramebuffer()");
6408     }
6409
6410     IWineD3DSurface_ModifyLocation(dst_surface, SFLAG_INDRAWABLE, TRUE);
6411
6412     if (This->render_offscreen) {
6413         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6414     } else {
6415         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
6416         checkGLcall("glBindFramebuffer()");
6417     }
6418
6419     /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
6420     if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer
6421             && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) {
6422         glDrawBuffer(GL_BACK);
6423         checkGLcall("glDrawBuffer()");
6424     }
6425     LEAVE_GL();
6426 }
6427
6428 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
6429     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6430     WINED3DVIEWPORT viewport;
6431
6432     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
6433
6434     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
6435         WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
6436              This, RenderTargetIndex, GL_LIMITS(buffers));
6437         return WINED3DERR_INVALIDCALL;
6438     }
6439
6440     /* MSDN says that null disables the render target
6441     but a device must always be associated with a render target
6442     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6443
6444     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6445     for more details
6446     */
6447     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
6448         FIXME("Trying to set render target 0 to NULL\n");
6449         return WINED3DERR_INVALIDCALL;
6450     }
6451     if (pRenderTarget && !(((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
6452         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);
6453         return WINED3DERR_INVALIDCALL;
6454     }
6455
6456     /* If we are trying to set what we already have, don't bother */
6457     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
6458         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6459         return WINED3D_OK;
6460     }
6461     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
6462     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
6463     This->render_targets[RenderTargetIndex] = pRenderTarget;
6464
6465     /* Render target 0 is special */
6466     if(RenderTargetIndex == 0) {
6467         /* Finally, reset the viewport as the MSDN states. */
6468         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
6469         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
6470         viewport.X      = 0;
6471         viewport.Y      = 0;
6472         viewport.MaxZ   = 1.0f;
6473         viewport.MinZ   = 0.0f;
6474         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
6475         /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
6476          * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
6477          */
6478         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
6479
6480         /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
6481          * ctx properly.
6482          * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
6483          * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
6484          */
6485         ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
6486     }
6487     return WINED3D_OK;
6488 }
6489
6490 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
6491     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6492     HRESULT  hr = WINED3D_OK;
6493     IWineD3DSurface *tmp;
6494
6495     TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This, This->stencilBufferTarget, pNewZStencil);
6496
6497     if (pNewZStencil == This->stencilBufferTarget) {
6498         TRACE("Trying to do a NOP SetRenderTarget operation\n");
6499     } else {
6500         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead
6501         * depending on the renter target implementation being used.
6502         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6503         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6504         * stencil buffer and incur an extra memory overhead
6505          ******************************************************/
6506
6507         tmp = This->stencilBufferTarget;
6508         This->stencilBufferTarget = pNewZStencil;
6509         This->depth_copy_state = WINED3D_DCS_NO_COPY;
6510         /* should we be calling the parent or the wined3d surface? */
6511         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
6512         if (NULL != tmp) IWineD3DSurface_Release(tmp);
6513         hr = WINED3D_OK;
6514
6515         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
6516             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
6517             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
6518             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
6519             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
6520         }
6521     }
6522
6523     return hr;
6524 }
6525
6526 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6527                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6528     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6529     /* TODO: the use of Impl is deprecated. */
6530     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6531     WINED3DLOCKED_RECT lockedRect;
6532
6533     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6534
6535     /* some basic validation checks */
6536     if(This->cursorTexture) {
6537         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6538         ENTER_GL();
6539         glDeleteTextures(1, &This->cursorTexture);
6540         LEAVE_GL();
6541         This->cursorTexture = 0;
6542     }
6543
6544     if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
6545         This->haveHardwareCursor = TRUE;
6546     else
6547         This->haveHardwareCursor = FALSE;
6548
6549     if(pCursorBitmap) {
6550         WINED3DLOCKED_RECT rect;
6551
6552         /* MSDN: Cursor must be A8R8G8B8 */
6553         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6554             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6555             return WINED3DERR_INVALIDCALL;
6556         }
6557
6558         /* MSDN: Cursor must be smaller than the display mode */
6559         if(pSur->currentDesc.Width > This->ddraw_width ||
6560            pSur->currentDesc.Height > This->ddraw_height) {
6561             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);
6562             return WINED3DERR_INVALIDCALL;
6563         }
6564
6565         if (!This->haveHardwareCursor) {
6566             /* TODO: MSDN: Cursor sizes must be a power of 2 */
6567
6568             /* Do not store the surface's pointer because the application may
6569              * release it after setting the cursor image. Windows doesn't
6570              * addref the set surface, so we can't do this either without
6571              * creating circular refcount dependencies. Copy out the gl texture
6572              * instead.
6573              */
6574             This->cursorWidth = pSur->currentDesc.Width;
6575             This->cursorHeight = pSur->currentDesc.Height;
6576             if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
6577             {
6578                 const GlPixelFormatDesc *glDesc;
6579                 const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(WINED3DFMT_A8R8G8B8, &GLINFO_LOCATION, &glDesc);
6580                 char *mem, *bits = (char *)rect.pBits;
6581                 GLint intfmt = glDesc->glInternal;
6582                 GLint format = glDesc->glFormat;
6583                 GLint type = glDesc->glType;
6584                 INT height = This->cursorHeight;
6585                 INT width = This->cursorWidth;
6586                 INT bpp = tableEntry->bpp;
6587                 INT i;
6588
6589                 /* Reformat the texture memory (pitch and width can be
6590                  * different) */
6591                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
6592                 for(i = 0; i < height; i++)
6593                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
6594                 IWineD3DSurface_UnlockRect(pCursorBitmap);
6595                 ENTER_GL();
6596
6597                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6598                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
6599                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6600                 }
6601
6602                 /* Make sure that a proper texture unit is selected */
6603                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
6604                     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
6605                     checkGLcall("glActiveTextureARB");
6606                 }
6607                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
6608                 /* Create a new cursor texture */
6609                 glGenTextures(1, &This->cursorTexture);
6610                 checkGLcall("glGenTextures");
6611                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
6612                 checkGLcall("glBindTexture");
6613                 /* Copy the bitmap memory into the cursor texture */
6614                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
6615                 HeapFree(GetProcessHeap(), 0, mem);
6616                 checkGLcall("glTexImage2D");
6617
6618                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
6619                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
6620                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6621                 }
6622
6623                 LEAVE_GL();
6624             }
6625             else
6626             {
6627                 FIXME("A cursor texture was not returned.\n");
6628                 This->cursorTexture = 0;
6629             }
6630         }
6631         else
6632         {
6633             /* Draw a hardware cursor */
6634             ICONINFO cursorInfo;
6635             HCURSOR cursor;
6636             /* Create and clear maskBits because it is not needed for
6637              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
6638              * chunks. */
6639             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6640                 (pSur->currentDesc.Width * pSur->currentDesc.Height / 8));
6641             IWineD3DSurface_LockRect(pCursorBitmap, &lockedRect, NULL,
6642                                          WINED3DLOCK_NO_DIRTY_UPDATE |
6643                                          WINED3DLOCK_READONLY
6644             );
6645             TRACE("width: %i height: %i\n", pSur->currentDesc.Width,
6646                   pSur->currentDesc.Height);
6647
6648             cursorInfo.fIcon = FALSE;
6649             cursorInfo.xHotspot = XHotSpot;
6650             cursorInfo.yHotspot = YHotSpot;
6651             cursorInfo.hbmMask = CreateBitmap(pSur->currentDesc.Width,
6652                                               pSur->currentDesc.Height, 1,
6653                                               1, &maskBits);
6654             cursorInfo.hbmColor = CreateBitmap(pSur->currentDesc.Width,
6655                                                pSur->currentDesc.Height, 1,
6656                                                32, lockedRect.pBits);
6657             IWineD3DSurface_UnlockRect(pCursorBitmap);
6658             /* Create our cursor and clean up. */
6659             cursor = CreateIconIndirect(&cursorInfo);
6660             SetCursor(cursor);
6661             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
6662             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
6663             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
6664             This->hardwareCursor = cursor;
6665             HeapFree(GetProcessHeap(), 0, maskBits);
6666         }
6667     }
6668
6669     This->xHotSpot = XHotSpot;
6670     This->yHotSpot = YHotSpot;
6671     return WINED3D_OK;
6672 }
6673
6674 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6675     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6676     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6677
6678     This->xScreenSpace = XScreenSpace;
6679     This->yScreenSpace = YScreenSpace;
6680
6681     return;
6682
6683 }
6684
6685 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6686     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6687     BOOL oldVisible = This->bCursorVisible;
6688     POINT pt;
6689
6690     TRACE("(%p) : visible(%d)\n", This, bShow);
6691
6692     /*
6693      * When ShowCursor is first called it should make the cursor appear at the OS's last
6694      * known cursor position.  Because of this, some applications just repetitively call
6695      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
6696      */
6697     GetCursorPos(&pt);
6698     This->xScreenSpace = pt.x;
6699     This->yScreenSpace = pt.y;
6700
6701     if (This->haveHardwareCursor) {
6702         This->bCursorVisible = bShow;
6703         if (bShow)
6704             SetCursor(This->hardwareCursor);
6705         else
6706             SetCursor(NULL);
6707     }
6708     else
6709     {
6710         if (This->cursorTexture)
6711             This->bCursorVisible = bShow;
6712     }
6713
6714     return oldVisible;
6715 }
6716
6717 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6718     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6719     IWineD3DResourceImpl *resource;
6720     TRACE("(%p) : state (%u)\n", This, This->state);
6721
6722     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6723     switch (This->state) {
6724     case WINED3D_OK:
6725         return WINED3D_OK;
6726     case WINED3DERR_DEVICELOST:
6727         {
6728             LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
6729                 if (resource->resource.pool == WINED3DPOOL_DEFAULT)
6730                     return WINED3DERR_DEVICENOTRESET;
6731             }
6732             return WINED3DERR_DEVICELOST;
6733         }
6734     case WINED3DERR_DRIVERINTERNALERROR:
6735         return WINED3DERR_DRIVERINTERNALERROR;
6736     }
6737
6738     /* Unknown state */
6739     return WINED3DERR_DRIVERINTERNALERROR;
6740 }
6741
6742
6743 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6744     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6745     /** FIXME: Resource tracking needs to be done,
6746     * The closes we can do to this is set the priorities of all managed textures low
6747     * and then reset them.
6748      ***********************************************************/
6749     FIXME("(%p) : stub\n", This);
6750     return WINED3D_OK;
6751 }
6752
6753 static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6754     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
6755
6756     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6757     if(surface->Flags & SFLAG_DIBSECTION) {
6758         /* Release the DC */
6759         SelectObject(surface->hDC, surface->dib.holdbitmap);
6760         DeleteDC(surface->hDC);
6761         /* Release the DIB section */
6762         DeleteObject(surface->dib.DIBsection);
6763         surface->dib.bitmap_data = NULL;
6764         surface->resource.allocatedMemory = NULL;
6765         surface->Flags &= ~SFLAG_DIBSECTION;
6766     }
6767     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
6768     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
6769     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
6770         surface->pow2Width = pPresentationParameters->BackBufferWidth;
6771         surface->pow2Height = pPresentationParameters->BackBufferHeight;
6772     } else {
6773         surface->pow2Width = surface->pow2Height = 1;
6774         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6775         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6776     }
6777     if(surface->glDescription.textureName) {
6778         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6779         ENTER_GL();
6780         glDeleteTextures(1, &surface->glDescription.textureName);
6781         LEAVE_GL();
6782         surface->glDescription.textureName = 0;
6783         surface->Flags &= ~SFLAG_CLIENT;
6784     }
6785     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
6786        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
6787         surface->Flags |= SFLAG_NONPOW2;
6788     } else  {
6789         surface->Flags &= ~SFLAG_NONPOW2;
6790     }
6791     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
6792     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6793 }
6794
6795 static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *data) {
6796     TRACE("Unloading resource %p\n", resource);
6797     IWineD3DResource_UnLoad(resource);
6798     IWineD3DResource_Release(resource);
6799     return S_OK;
6800 }
6801
6802 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6803     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6804     IWineD3DSwapChainImpl *swapchain;
6805     HRESULT hr;
6806     BOOL DisplayModeChanged = FALSE;
6807     WINED3DDISPLAYMODE mode;
6808     IWineD3DBaseShaderImpl *shader;
6809     TRACE("(%p)\n", This);
6810
6811     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6812     if(FAILED(hr)) {
6813         ERR("Failed to get the first implicit swapchain\n");
6814         return hr;
6815     }
6816
6817     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6818      * on an existing gl context, so there's no real need for recreation.
6819      *
6820      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6821      *
6822      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6823      */
6824     TRACE("New params:\n");
6825     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
6826     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
6827     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
6828     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
6829     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
6830     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
6831     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
6832     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
6833     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
6834     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6835     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
6836     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
6837     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
6838
6839     /* No special treatment of these parameters. Just store them */
6840     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
6841     swapchain->presentParms.Flags = pPresentationParameters->Flags;
6842     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
6843     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
6844
6845     /* What to do about these? */
6846     if(pPresentationParameters->BackBufferCount != 0 &&
6847         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6848         ERR("Cannot change the back buffer count yet\n");
6849     }
6850     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6851         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6852         ERR("Cannot change the back buffer format yet\n");
6853     }
6854     if(pPresentationParameters->hDeviceWindow != NULL &&
6855         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6856         ERR("Cannot change the device window yet\n");
6857     }
6858     if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
6859         ERR("What do do about a changed auto depth stencil parameter?\n");
6860     }
6861
6862     IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL);
6863     LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) {
6864         This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader);
6865     }
6866
6867     if(pPresentationParameters->Windowed) {
6868         mode.Width = swapchain->orig_width;
6869         mode.Height = swapchain->orig_height;
6870         mode.RefreshRate = 0;
6871         mode.Format = swapchain->presentParms.BackBufferFormat;
6872     } else {
6873         mode.Width = pPresentationParameters->BackBufferWidth;
6874         mode.Height = pPresentationParameters->BackBufferHeight;
6875         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
6876         mode.Format = swapchain->presentParms.BackBufferFormat;
6877     }
6878
6879     /* Should Width == 800 && Height == 0 set 800x600? */
6880     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
6881        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6882         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6883     {
6884         WINED3DVIEWPORT vp;
6885         int i;
6886
6887         vp.X = 0;
6888         vp.Y = 0;
6889         vp.Width = pPresentationParameters->BackBufferWidth;
6890         vp.Height = pPresentationParameters->BackBufferHeight;
6891         vp.MinZ = 0;
6892         vp.MaxZ = 1;
6893
6894         if(!pPresentationParameters->Windowed) {
6895             DisplayModeChanged = TRUE;
6896         }
6897         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
6898         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
6899
6900         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
6901         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
6902             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
6903         }
6904
6905         /* Now set the new viewport */
6906         IWineD3DDevice_SetViewport(iface, &vp);
6907     }
6908
6909     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
6910        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
6911         DisplayModeChanged) {
6912
6913         /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
6914         if(!pPresentationParameters->Windowed) {
6915             IWineD3DDevice_SetFullscreen(iface, TRUE);
6916         }
6917
6918         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6919
6920         /* Switching out of fullscreen mode? First set the original res, then change the window */
6921         if(pPresentationParameters->Windowed) {
6922             IWineD3DDevice_SetFullscreen(iface, FALSE);
6923         }
6924         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
6925     }
6926
6927     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6928     return WINED3D_OK;
6929 }
6930
6931 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6932     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6933     /** FIXME: always true at the moment **/
6934     if(!bEnableDialogs) {
6935         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6936     }
6937     return WINED3D_OK;
6938 }
6939
6940
6941 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6942     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6943     TRACE("(%p) : pParameters %p\n", This, pParameters);
6944
6945     *pParameters = This->createParms;
6946     return WINED3D_OK;
6947 }
6948
6949 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6950     IWineD3DSwapChain *swapchain;
6951     HRESULT hrc = WINED3D_OK;
6952
6953     TRACE("Relaying  to swapchain\n");
6954
6955     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6956         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6957         IWineD3DSwapChain_Release(swapchain);
6958     }
6959     return;
6960 }
6961
6962 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6963     IWineD3DSwapChain *swapchain;
6964     HRESULT hrc = WINED3D_OK;
6965
6966     TRACE("Relaying  to swapchain\n");
6967
6968     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6969         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6970         IWineD3DSwapChain_Release(swapchain);
6971     }
6972     return;
6973 }
6974
6975
6976 /** ********************************************************
6977 *   Notification functions
6978 ** ********************************************************/
6979 /** This function must be called in the release of a resource when ref == 0,
6980 * the contents of resource must still be correct,
6981 * any handles to other resource held by the caller must be closed
6982 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6983  *****************************************************/
6984 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6985     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6986
6987     TRACE("(%p) : Adding Resource %p\n", This, resource);
6988     list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6989 }
6990
6991 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6992     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6993
6994     TRACE("(%p) : Removing resource %p\n", This, resource);
6995
6996     list_remove(&((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
6997 }
6998
6999
7000 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
7001     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7002     int counter;
7003
7004     TRACE("(%p) : resource %p\n", This, resource);
7005     switch(IWineD3DResource_GetType(resource)){
7006         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
7007         case WINED3DRTYPE_SURFACE: {
7008             unsigned int i;
7009
7010             /* Cleanup any FBO attachments if d3d is enabled */
7011             if(This->d3d_initialized) {
7012                 if((IWineD3DSurface *)resource == This->lastActiveRenderTarget) {
7013                     IWineD3DSwapChainImpl *swapchain = This->swapchains ? (IWineD3DSwapChainImpl *) This->swapchains[0] : NULL;
7014
7015                     TRACE("Last active render target destroyed\n");
7016                     /* Find a replacement surface for the currently active back buffer. The context manager does not do NULL
7017                      * checks, so switch to a valid target as long as the currently set surface is still valid. Use the
7018                      * surface of the implicit swpchain. If that is the same as the destroyed surface the device is destroyed
7019                      * and the lastActiveRenderTarget member shouldn't matter
7020                      */
7021                     if(swapchain) {
7022                         if(swapchain->backBuffer && swapchain->backBuffer[0] != (IWineD3DSurface *)resource) {
7023                             TRACE("Activating primary back buffer\n");
7024                             ActivateContext(This, swapchain->backBuffer[0], CTXUSAGE_RESOURCELOAD);
7025                         } else if(!swapchain->backBuffer && swapchain->frontBuffer != (IWineD3DSurface *)resource) {
7026                             /* Single buffering environment */
7027                             TRACE("Activating primary front buffer\n");
7028                             ActivateContext(This, swapchain->frontBuffer, CTXUSAGE_RESOURCELOAD);
7029                         } else {
7030                             TRACE("Device is being destroyed, setting lastActiveRenderTarget = 0xdeadbabe\n");
7031                             /* Implicit render target destroyed, that means the device is being destroyed
7032                              * whatever we set here, it shouldn't matter
7033                              */
7034                             This->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadbabe;
7035                         }
7036                     } else {
7037                         /* May happen during ddraw uninitialization */
7038                         TRACE("Render target set, but swapchain does not exist!\n");
7039                         This->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadcafe;
7040                     }
7041                 }
7042
7043                 for (i = 0; i < GL_LIMITS(buffers); ++i) {
7044                     if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) {
7045                         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
7046                         set_render_target_fbo(iface, i, NULL);
7047                         This->fbo_color_attachments[i] = NULL;
7048                     }
7049                 }
7050                 if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) {
7051                     bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
7052                     set_depth_stencil_fbo(iface, NULL);
7053                     This->fbo_depth_attachment = NULL;
7054                 }
7055             }
7056
7057             break;
7058         }
7059         case WINED3DRTYPE_TEXTURE:
7060         case WINED3DRTYPE_CUBETEXTURE:
7061         case WINED3DRTYPE_VOLUMETEXTURE:
7062                 for (counter = 0; counter < MAX_COMBINED_SAMPLERS; counter++) {
7063                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7064                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7065                         This->stateBlock->textures[counter] = NULL;
7066                     }
7067                     if (This->updateStateBlock != This->stateBlock ){
7068                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
7069                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
7070                             This->updateStateBlock->textures[counter] = NULL;
7071                         }
7072                     }
7073                 }
7074         break;
7075         case WINED3DRTYPE_VOLUME:
7076         /* TODO: nothing really? */
7077         break;
7078         case WINED3DRTYPE_VERTEXBUFFER:
7079         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7080         {
7081             int streamNumber;
7082             TRACE("Cleaning up stream pointers\n");
7083
7084             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
7085                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7086                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7087                 */
7088                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7089                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
7090                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7091                         This->updateStateBlock->streamSource[streamNumber] = 0;
7092                         /* Set changed flag? */
7093                     }
7094                 }
7095                 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) */
7096                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
7097                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
7098                         This->stateBlock->streamSource[streamNumber] = 0;
7099                     }
7100                 }
7101 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7102                  else { /* This shouldn't happen */
7103                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7104                 }
7105 #endif
7106
7107             }
7108         }
7109         break;
7110         case WINED3DRTYPE_INDEXBUFFER:
7111         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7112         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
7113             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7114                 This->updateStateBlock->pIndexData =  NULL;
7115             }
7116         }
7117         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
7118             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
7119                 This->stateBlock->pIndexData =  NULL;
7120             }
7121         }
7122
7123         break;
7124         default:
7125         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
7126         break;
7127     }
7128
7129
7130     /* Remove the resource from the resourceStore */
7131     IWineD3DDeviceImpl_RemoveResource(iface, resource);
7132
7133     TRACE("Resource released\n");
7134
7135 }
7136
7137 static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
7138     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
7139     IWineD3DResourceImpl *resource, *cursor;
7140     HRESULT ret;
7141     TRACE("(%p)->(%p,%p)\n", This, pCallback, pData);
7142
7143     LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
7144         TRACE("enumerating resource %p\n", resource);
7145         IWineD3DResource_AddRef((IWineD3DResource *) resource);
7146         ret = pCallback((IWineD3DResource *) resource, pData);
7147         if(ret == S_FALSE) {
7148             TRACE("Canceling enumeration\n");
7149             break;
7150         }
7151     }
7152     return WINED3D_OK;
7153 }
7154
7155 /**********************************************************
7156  * IWineD3DDevice VTbl follows
7157  **********************************************************/
7158
7159 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
7160 {
7161     /*** IUnknown methods ***/
7162     IWineD3DDeviceImpl_QueryInterface,
7163     IWineD3DDeviceImpl_AddRef,
7164     IWineD3DDeviceImpl_Release,
7165     /*** IWineD3DDevice methods ***/
7166     IWineD3DDeviceImpl_GetParent,
7167     /*** Creation methods**/
7168     IWineD3DDeviceImpl_CreateVertexBuffer,
7169     IWineD3DDeviceImpl_CreateIndexBuffer,
7170     IWineD3DDeviceImpl_CreateStateBlock,
7171     IWineD3DDeviceImpl_CreateSurface,
7172     IWineD3DDeviceImpl_CreateTexture,
7173     IWineD3DDeviceImpl_CreateVolumeTexture,
7174     IWineD3DDeviceImpl_CreateVolume,
7175     IWineD3DDeviceImpl_CreateCubeTexture,
7176     IWineD3DDeviceImpl_CreateQuery,
7177     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
7178     IWineD3DDeviceImpl_CreateVertexDeclaration,
7179     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
7180     IWineD3DDeviceImpl_CreateVertexShader,
7181     IWineD3DDeviceImpl_CreatePixelShader,
7182     IWineD3DDeviceImpl_CreatePalette,
7183     /*** Odd functions **/
7184     IWineD3DDeviceImpl_Init3D,
7185     IWineD3DDeviceImpl_Uninit3D,
7186     IWineD3DDeviceImpl_SetFullscreen,
7187     IWineD3DDeviceImpl_SetMultithreaded,
7188     IWineD3DDeviceImpl_EvictManagedResources,
7189     IWineD3DDeviceImpl_GetAvailableTextureMem,
7190     IWineD3DDeviceImpl_GetBackBuffer,
7191     IWineD3DDeviceImpl_GetCreationParameters,
7192     IWineD3DDeviceImpl_GetDeviceCaps,
7193     IWineD3DDeviceImpl_GetDirect3D,
7194     IWineD3DDeviceImpl_GetDisplayMode,
7195     IWineD3DDeviceImpl_SetDisplayMode,
7196     IWineD3DDeviceImpl_GetHWND,
7197     IWineD3DDeviceImpl_SetHWND,
7198     IWineD3DDeviceImpl_GetNumberOfSwapChains,
7199     IWineD3DDeviceImpl_GetRasterStatus,
7200     IWineD3DDeviceImpl_GetSwapChain,
7201     IWineD3DDeviceImpl_Reset,
7202     IWineD3DDeviceImpl_SetDialogBoxMode,
7203     IWineD3DDeviceImpl_SetCursorProperties,
7204     IWineD3DDeviceImpl_SetCursorPosition,
7205     IWineD3DDeviceImpl_ShowCursor,
7206     IWineD3DDeviceImpl_TestCooperativeLevel,
7207     /*** Getters and setters **/
7208     IWineD3DDeviceImpl_SetClipPlane,
7209     IWineD3DDeviceImpl_GetClipPlane,
7210     IWineD3DDeviceImpl_SetClipStatus,
7211     IWineD3DDeviceImpl_GetClipStatus,
7212     IWineD3DDeviceImpl_SetCurrentTexturePalette,
7213     IWineD3DDeviceImpl_GetCurrentTexturePalette,
7214     IWineD3DDeviceImpl_SetDepthStencilSurface,
7215     IWineD3DDeviceImpl_GetDepthStencilSurface,
7216     IWineD3DDeviceImpl_SetFVF,
7217     IWineD3DDeviceImpl_GetFVF,
7218     IWineD3DDeviceImpl_SetGammaRamp,
7219     IWineD3DDeviceImpl_GetGammaRamp,
7220     IWineD3DDeviceImpl_SetIndices,
7221     IWineD3DDeviceImpl_GetIndices,
7222     IWineD3DDeviceImpl_SetBaseVertexIndex,
7223     IWineD3DDeviceImpl_GetBaseVertexIndex,
7224     IWineD3DDeviceImpl_SetLight,
7225     IWineD3DDeviceImpl_GetLight,
7226     IWineD3DDeviceImpl_SetLightEnable,
7227     IWineD3DDeviceImpl_GetLightEnable,
7228     IWineD3DDeviceImpl_SetMaterial,
7229     IWineD3DDeviceImpl_GetMaterial,
7230     IWineD3DDeviceImpl_SetNPatchMode,
7231     IWineD3DDeviceImpl_GetNPatchMode,
7232     IWineD3DDeviceImpl_SetPaletteEntries,
7233     IWineD3DDeviceImpl_GetPaletteEntries,
7234     IWineD3DDeviceImpl_SetPixelShader,
7235     IWineD3DDeviceImpl_GetPixelShader,
7236     IWineD3DDeviceImpl_SetPixelShaderConstantB,
7237     IWineD3DDeviceImpl_GetPixelShaderConstantB,
7238     IWineD3DDeviceImpl_SetPixelShaderConstantI,
7239     IWineD3DDeviceImpl_GetPixelShaderConstantI,
7240     IWineD3DDeviceImpl_SetPixelShaderConstantF,
7241     IWineD3DDeviceImpl_GetPixelShaderConstantF,
7242     IWineD3DDeviceImpl_SetRenderState,
7243     IWineD3DDeviceImpl_GetRenderState,
7244     IWineD3DDeviceImpl_SetRenderTarget,
7245     IWineD3DDeviceImpl_GetRenderTarget,
7246     IWineD3DDeviceImpl_SetFrontBackBuffers,
7247     IWineD3DDeviceImpl_SetSamplerState,
7248     IWineD3DDeviceImpl_GetSamplerState,
7249     IWineD3DDeviceImpl_SetScissorRect,
7250     IWineD3DDeviceImpl_GetScissorRect,
7251     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
7252     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
7253     IWineD3DDeviceImpl_SetStreamSource,
7254     IWineD3DDeviceImpl_GetStreamSource,
7255     IWineD3DDeviceImpl_SetStreamSourceFreq,
7256     IWineD3DDeviceImpl_GetStreamSourceFreq,
7257     IWineD3DDeviceImpl_SetTexture,
7258     IWineD3DDeviceImpl_GetTexture,
7259     IWineD3DDeviceImpl_SetTextureStageState,
7260     IWineD3DDeviceImpl_GetTextureStageState,
7261     IWineD3DDeviceImpl_SetTransform,
7262     IWineD3DDeviceImpl_GetTransform,
7263     IWineD3DDeviceImpl_SetVertexDeclaration,
7264     IWineD3DDeviceImpl_GetVertexDeclaration,
7265     IWineD3DDeviceImpl_SetVertexShader,
7266     IWineD3DDeviceImpl_GetVertexShader,
7267     IWineD3DDeviceImpl_SetVertexShaderConstantB,
7268     IWineD3DDeviceImpl_GetVertexShaderConstantB,
7269     IWineD3DDeviceImpl_SetVertexShaderConstantI,
7270     IWineD3DDeviceImpl_GetVertexShaderConstantI,
7271     IWineD3DDeviceImpl_SetVertexShaderConstantF,
7272     IWineD3DDeviceImpl_GetVertexShaderConstantF,
7273     IWineD3DDeviceImpl_SetViewport,
7274     IWineD3DDeviceImpl_GetViewport,
7275     IWineD3DDeviceImpl_MultiplyTransform,
7276     IWineD3DDeviceImpl_ValidateDevice,
7277     IWineD3DDeviceImpl_ProcessVertices,
7278     /*** State block ***/
7279     IWineD3DDeviceImpl_BeginStateBlock,
7280     IWineD3DDeviceImpl_EndStateBlock,
7281     /*** Scene management ***/
7282     IWineD3DDeviceImpl_BeginScene,
7283     IWineD3DDeviceImpl_EndScene,
7284     IWineD3DDeviceImpl_Present,
7285     IWineD3DDeviceImpl_Clear,
7286     /*** Drawing ***/
7287     IWineD3DDeviceImpl_DrawPrimitive,
7288     IWineD3DDeviceImpl_DrawIndexedPrimitive,
7289     IWineD3DDeviceImpl_DrawPrimitiveUP,
7290     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
7291     IWineD3DDeviceImpl_DrawPrimitiveStrided,
7292     IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided,
7293     IWineD3DDeviceImpl_DrawRectPatch,
7294     IWineD3DDeviceImpl_DrawTriPatch,
7295     IWineD3DDeviceImpl_DeletePatch,
7296     IWineD3DDeviceImpl_ColorFill,
7297     IWineD3DDeviceImpl_UpdateTexture,
7298     IWineD3DDeviceImpl_UpdateSurface,
7299     IWineD3DDeviceImpl_GetFrontBufferData,
7300     /*** object tracking ***/
7301     IWineD3DDeviceImpl_ResourceReleased,
7302     IWineD3DDeviceImpl_EnumResources
7303 };
7304
7305
7306 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
7307     WINED3DRS_ALPHABLENDENABLE   ,
7308     WINED3DRS_ALPHAFUNC          ,
7309     WINED3DRS_ALPHAREF           ,
7310     WINED3DRS_ALPHATESTENABLE    ,
7311     WINED3DRS_BLENDOP            ,
7312     WINED3DRS_COLORWRITEENABLE   ,
7313     WINED3DRS_DESTBLEND          ,
7314     WINED3DRS_DITHERENABLE       ,
7315     WINED3DRS_FILLMODE           ,
7316     WINED3DRS_FOGDENSITY         ,
7317     WINED3DRS_FOGEND             ,
7318     WINED3DRS_FOGSTART           ,
7319     WINED3DRS_LASTPIXEL          ,
7320     WINED3DRS_SHADEMODE          ,
7321     WINED3DRS_SRCBLEND           ,
7322     WINED3DRS_STENCILENABLE      ,
7323     WINED3DRS_STENCILFAIL        ,
7324     WINED3DRS_STENCILFUNC        ,
7325     WINED3DRS_STENCILMASK        ,
7326     WINED3DRS_STENCILPASS        ,
7327     WINED3DRS_STENCILREF         ,
7328     WINED3DRS_STENCILWRITEMASK   ,
7329     WINED3DRS_STENCILZFAIL       ,
7330     WINED3DRS_TEXTUREFACTOR      ,
7331     WINED3DRS_WRAP0              ,
7332     WINED3DRS_WRAP1              ,
7333     WINED3DRS_WRAP2              ,
7334     WINED3DRS_WRAP3              ,
7335     WINED3DRS_WRAP4              ,
7336     WINED3DRS_WRAP5              ,
7337     WINED3DRS_WRAP6              ,
7338     WINED3DRS_WRAP7              ,
7339     WINED3DRS_ZENABLE            ,
7340     WINED3DRS_ZFUNC              ,
7341     WINED3DRS_ZWRITEENABLE
7342 };
7343
7344 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
7345     WINED3DTSS_ADDRESSW              ,
7346     WINED3DTSS_ALPHAARG0             ,
7347     WINED3DTSS_ALPHAARG1             ,
7348     WINED3DTSS_ALPHAARG2             ,
7349     WINED3DTSS_ALPHAOP               ,
7350     WINED3DTSS_BUMPENVLOFFSET        ,
7351     WINED3DTSS_BUMPENVLSCALE         ,
7352     WINED3DTSS_BUMPENVMAT00          ,
7353     WINED3DTSS_BUMPENVMAT01          ,
7354     WINED3DTSS_BUMPENVMAT10          ,
7355     WINED3DTSS_BUMPENVMAT11          ,
7356     WINED3DTSS_COLORARG0             ,
7357     WINED3DTSS_COLORARG1             ,
7358     WINED3DTSS_COLORARG2             ,
7359     WINED3DTSS_COLOROP               ,
7360     WINED3DTSS_RESULTARG             ,
7361     WINED3DTSS_TEXCOORDINDEX         ,
7362     WINED3DTSS_TEXTURETRANSFORMFLAGS
7363 };
7364
7365 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
7366     WINED3DSAMP_ADDRESSU         ,
7367     WINED3DSAMP_ADDRESSV         ,
7368     WINED3DSAMP_ADDRESSW         ,
7369     WINED3DSAMP_BORDERCOLOR      ,
7370     WINED3DSAMP_MAGFILTER        ,
7371     WINED3DSAMP_MINFILTER        ,
7372     WINED3DSAMP_MIPFILTER        ,
7373     WINED3DSAMP_MIPMAPLODBIAS    ,
7374     WINED3DSAMP_MAXMIPLEVEL      ,
7375     WINED3DSAMP_MAXANISOTROPY    ,
7376     WINED3DSAMP_SRGBTEXTURE      ,
7377     WINED3DSAMP_ELEMENTINDEX
7378 };
7379
7380 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
7381     WINED3DRS_AMBIENT                       ,
7382     WINED3DRS_AMBIENTMATERIALSOURCE         ,
7383     WINED3DRS_CLIPPING                      ,
7384     WINED3DRS_CLIPPLANEENABLE               ,
7385     WINED3DRS_COLORVERTEX                   ,
7386     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
7387     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
7388     WINED3DRS_FOGDENSITY                    ,
7389     WINED3DRS_FOGEND                        ,
7390     WINED3DRS_FOGSTART                      ,
7391     WINED3DRS_FOGTABLEMODE                  ,
7392     WINED3DRS_FOGVERTEXMODE                 ,
7393     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
7394     WINED3DRS_LIGHTING                      ,
7395     WINED3DRS_LOCALVIEWER                   ,
7396     WINED3DRS_MULTISAMPLEANTIALIAS          ,
7397     WINED3DRS_MULTISAMPLEMASK               ,
7398     WINED3DRS_NORMALIZENORMALS              ,
7399     WINED3DRS_PATCHEDGESTYLE                ,
7400     WINED3DRS_POINTSCALE_A                  ,
7401     WINED3DRS_POINTSCALE_B                  ,
7402     WINED3DRS_POINTSCALE_C                  ,
7403     WINED3DRS_POINTSCALEENABLE              ,
7404     WINED3DRS_POINTSIZE                     ,
7405     WINED3DRS_POINTSIZE_MAX                 ,
7406     WINED3DRS_POINTSIZE_MIN                 ,
7407     WINED3DRS_POINTSPRITEENABLE             ,
7408     WINED3DRS_RANGEFOGENABLE                ,
7409     WINED3DRS_SPECULARMATERIALSOURCE        ,
7410     WINED3DRS_TWEENFACTOR                   ,
7411     WINED3DRS_VERTEXBLEND                   ,
7412     WINED3DRS_CULLMODE                      ,
7413     WINED3DRS_FOGCOLOR
7414 };
7415
7416 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
7417     WINED3DTSS_TEXCOORDINDEX         ,
7418     WINED3DTSS_TEXTURETRANSFORMFLAGS
7419 };
7420
7421 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
7422     WINED3DSAMP_DMAPOFFSET
7423 };
7424
7425 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
7426     DWORD rep = StateTable[state].representative;
7427     DWORD idx;
7428     BYTE shift;
7429     UINT i;
7430     WineD3DContext *context;
7431
7432     if(!rep) return;
7433     for(i = 0; i < This->numContexts; i++) {
7434         context = This->contexts[i];
7435         if(isStateDirty(context, rep)) continue;
7436
7437         context->dirtyArray[context->numDirtyEntries++] = rep;
7438         idx = rep >> 5;
7439         shift = rep & 0x1f;
7440         context->isStateDirty[idx] |= (1 << shift);
7441     }
7442 }
7443
7444 void get_drawable_size_pbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7445     IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
7446     /* The drawable size of a pbuffer render target is the current pbuffer size
7447      */
7448     *width = dev->pbufferWidth;
7449     *height = dev->pbufferHeight;
7450 }
7451
7452 void get_drawable_size_fbo(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7453     /* The drawable size of a fbo target is the opengl texture size, which is the power of two size
7454      */
7455     *width = This->pow2Width;
7456     *height = This->pow2Height;
7457 }
7458
7459 void get_drawable_size_backbuffer(IWineD3DSurfaceImpl *This, UINT *width, UINT *height) {
7460     IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
7461     /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
7462      * current context's drawable, which is the size of the back buffer of the swapchain
7463      * the active context belongs to. The back buffer of the swapchain is stored as the
7464      * surface the context belongs to.
7465      */
7466     *width = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Width;
7467     *height = ((IWineD3DSurfaceImpl *) dev->activeContext->surface)->currentDesc.Height;
7468 }