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