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