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