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