wined3d: Some render target->texture blit context handling.
[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 This->adapter->gl_info
37
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light = {
40
41     WINED3DLIGHT_DIRECTIONAL, /* Type */
42     { 1.0, 1.0, 1.0, 0.0 },   /* Diffuse r,g,b,a */
43     { 0.0, 0.0, 0.0, 0.0 },   /* Specular r,g,b,a */
44     { 0.0, 0.0, 0.0, 0.0 },   /* Ambient r,g,b,a, */
45     { 0.0, 0.0, 0.0 },        /* Position x,y,z */
46     { 0.0, 0.0, 1.0 },        /* Direction x,y,z */
47     0.0,                      /* Range */
48     0.0,                      /* Falloff */
49     0.0, 0.0, 0.0,            /* Attenuation 0,1,2 */
50     0.0,                      /* Theta */
51     0.0                       /* Phi */
52 };
53
54 /* 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     /* Setup all the devices defaults */
1860     IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1861 #if 0
1862     IWineD3DImpl_CheckGraphicsMemory();
1863 #endif
1864
1865     { /* Set a default viewport */
1866         WINED3DVIEWPORT vp;
1867         vp.X      = 0;
1868         vp.Y      = 0;
1869         vp.Width  = pPresentationParameters->BackBufferWidth;
1870         vp.Height = pPresentationParameters->BackBufferHeight;
1871         vp.MinZ   = 0.0f;
1872         vp.MaxZ   = 1.0f;
1873         IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1874     }
1875
1876     /* Initialize the current view state */
1877     This->view_ident = 1;
1878     This->contexts[0]->last_was_rhw = 0;
1879     glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1880     checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
1881
1882     switch(wined3d_settings.offscreen_rendering_mode) {
1883         case ORM_FBO:
1884         case ORM_PBUFFER:
1885             This->offscreenBuffer = GL_BACK;
1886             break;
1887
1888         case ORM_BACKBUFFER:
1889         {
1890             if(GL_LIMITS(aux_buffers) > 0) {
1891                 TRACE("Using auxilliary buffer for offscreen rendering\n");
1892                 This->offscreenBuffer = GL_AUX0;
1893             } else {
1894                 TRACE("Using back buffer for offscreen rendering\n");
1895                 This->offscreenBuffer = GL_BACK;
1896             }
1897         }
1898     }
1899
1900     TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1901     LEAVE_GL();
1902
1903     /* Clear the screen */
1904     IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL,
1905                           WINED3DCLEAR_TARGET | pPresentationParameters->EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0,
1906                           0x00, 1.0, 0);
1907
1908     This->d3d_initialized = TRUE;
1909     return WINED3D_OK;
1910 }
1911
1912 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
1913     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1914     int sampler;
1915     uint i;
1916     TRACE("(%p)\n", This);
1917
1918     if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1919
1920     ENTER_GL();
1921     /* I don't think that the interface guarants that the device is destroyed from the same thread
1922      * it was created. Thus make sure a context is active for the glDelete* calls
1923      */
1924     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
1925     LEAVE_GL();
1926
1927     /* Delete the pbuffer context if there is any */
1928     if(This->pbufferContext) DestroyContext(This, This->pbufferContext);
1929
1930     /* Delete the mouse cursor texture */
1931     if(This->cursorTexture) {
1932         ENTER_GL();
1933         glDeleteTextures(1, &This->cursorTexture);
1934         LEAVE_GL();
1935         This->cursorTexture = 0;
1936     }
1937
1938     for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
1939         IWineD3DDevice_SetTexture(iface, sampler, NULL);
1940     }
1941
1942     /* Release the buffers (with sanity checks)*/
1943     TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1944     if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1945         if(This->depthStencilBuffer != This->stencilBufferTarget)
1946             FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1947     }
1948     This->stencilBufferTarget = NULL;
1949
1950     TRACE("Releasing the render target at %p\n", This->render_targets[0]);
1951     if(IWineD3DSurface_Release(This->render_targets[0]) >0){
1952           /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1953     }
1954     TRACE("Setting rendertarget to NULL\n");
1955     This->render_targets[0] = NULL;
1956
1957     if (This->depthStencilBuffer) {
1958         if(D3DCB_DestroyDepthStencilSurface(This->depthStencilBuffer) > 0) {
1959             FIXME("(%p) Something's still holding the depthStencilBuffer\n", This);
1960         }
1961         This->depthStencilBuffer = NULL;
1962     }
1963
1964     for(i=0; i < This->NumberOfSwapChains; i++) {
1965         TRACE("Releasing the implicit swapchain %d\n", i);
1966         if (D3DCB_DestroySwapChain(This->swapchains[i])  > 0) {
1967             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1968         }
1969     }
1970
1971     HeapFree(GetProcessHeap(), 0, This->swapchains);
1972     This->swapchains = NULL;
1973     This->NumberOfSwapChains = 0;
1974
1975     This->d3d_initialized = FALSE;
1976     return WINED3D_OK;
1977 }
1978
1979 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
1980     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1981     TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
1982
1983     /* Setup the window for fullscreen mode */
1984     if(fullscreen && !This->ddraw_fullscreen) {
1985         IWineD3DDeviceImpl_SetupFullscreenWindow(iface, This->ddraw_window);
1986     } else if(!fullscreen && This->ddraw_fullscreen) {
1987         IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
1988     }
1989
1990     /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
1991      * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
1992      * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
1993      * separately.
1994      */
1995     This->ddraw_fullscreen = fullscreen;
1996 }
1997
1998 /* Enables thead safety in the wined3d device and its resources. Called by DirectDraw
1999  * from SetCooperativeLeven if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
2000  * CreateDevice if D3DCREATE_MULTITHREADED is passed.
2001  *
2002  * There is no way to deactivate thread safety once it is enabled
2003  */
2004 static void WINAPI IWineD3DDeviceImpl_SetMultithreaded(IWineD3DDevice *iface) {
2005     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2006     FIXME("No thread safety in wined3d yet\n");
2007
2008     /*For now just store the flag(needed in case of ddraw) */
2009     This->createParms.BehaviorFlags |= WINED3DCREATE_MULTITHREADED;
2010
2011     return;
2012 }
2013
2014 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
2015     DEVMODEW devmode;
2016     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2017     LONG ret;
2018     const PixelFormatDesc *formatDesc  = getFormatDescEntry(pMode->Format);
2019     RECT clip_rc;
2020
2021     TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2022
2023     /* Resize the screen even without a window:
2024      * The app could have unset it with SetCooperativeLevel, but not called
2025      * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2026      * but we don't have any hwnd
2027      */
2028
2029     devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2030     devmode.dmBitsPerPel = formatDesc->bpp * 8;
2031     if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
2032     devmode.dmPelsWidth  = pMode->Width;
2033     devmode.dmPelsHeight = pMode->Height;
2034
2035     devmode.dmDisplayFrequency = pMode->RefreshRate;
2036     if (pMode->RefreshRate != 0)  {
2037         devmode.dmFields |= DM_DISPLAYFREQUENCY;
2038     }
2039
2040     /* Only change the mode if necessary */
2041     if( (This->ddraw_width == pMode->Width) &&
2042         (This->ddraw_height == pMode->Height) &&
2043         (This->ddraw_format == pMode->Format) &&
2044         (pMode->RefreshRate == 0) ) {
2045         return WINED3D_OK;
2046     }
2047
2048     ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2049     if (ret != DISP_CHANGE_SUCCESSFUL) {
2050         if(devmode.dmDisplayFrequency != 0) {
2051             WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2052             devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2053             devmode.dmDisplayFrequency = 0;
2054             ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2055         }
2056         if(ret != DISP_CHANGE_SUCCESSFUL) {
2057             return WINED3DERR_NOTAVAILABLE;
2058         }
2059     }
2060
2061     /* Store the new values */
2062     This->ddraw_width = pMode->Width;
2063     This->ddraw_height = pMode->Height;
2064     This->ddraw_format = pMode->Format;
2065
2066     /* Only do this with a window of course */
2067     if(This->ddraw_window)
2068       MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2069
2070     /* And finally clip mouse to our screen */
2071     SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
2072     ClipCursor(&clip_rc);
2073
2074     return WINED3D_OK;
2075 }
2076
2077 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2078    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2079    *ppD3D= This->wineD3D;
2080    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
2081    IWineD3D_AddRef(*ppD3D);
2082    return WINED3D_OK;
2083 }
2084
2085 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2086     /** NOTE: There's a probably  a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
2087     * into the video ram as possible and seeing how many fit
2088     * you can also get the correct initial value from nvidia and ATI's driver via X
2089     * texture memory is video memory + AGP memory
2090     *******************/
2091     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2092     static BOOL showfixmes = TRUE;
2093     if (showfixmes) {
2094         FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2095          (wined3d_settings.emulated_textureram/(1024*1024)),
2096          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2097          showfixmes = FALSE;
2098     }
2099     TRACE("(%p) : simulating %dMB, returning %dMB left\n",  This,
2100          (wined3d_settings.emulated_textureram/(1024*1024)),
2101          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2102     /* return simulated texture memory left */
2103     return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2104 }
2105
2106
2107
2108 /*****
2109  * Get / Set FVF
2110  *****/
2111 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2112     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2113
2114     /* Update the current state block */
2115     This->updateStateBlock->changed.fvf      = TRUE;
2116     This->updateStateBlock->set.fvf          = TRUE;
2117
2118     if(This->updateStateBlock->fvf == fvf) {
2119         TRACE("Application is setting the old fvf over, nothing to do\n");
2120         return WINED3D_OK;
2121     }
2122
2123     This->updateStateBlock->fvf              = fvf;
2124     TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2125     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
2126     return WINED3D_OK;
2127 }
2128
2129
2130 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2131     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2132     TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2133     *pfvf = This->stateBlock->fvf;
2134     return WINED3D_OK;
2135 }
2136
2137 /*****
2138  * Get / Set Stream Source
2139  *****/
2140 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2141         IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
2142     IWineD3DVertexBuffer     *oldSrc;
2143
2144     if (StreamNumber >= MAX_STREAMS) {
2145         WARN("Stream out of range %d\n", StreamNumber);
2146         return WINED3DERR_INVALIDCALL;
2147     }
2148
2149     oldSrc = This->stateBlock->streamSource[StreamNumber];
2150     TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This, StreamNumber, oldSrc, pStreamData, OffsetInBytes, Stride);
2151
2152     This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2153     This->updateStateBlock->set.streamSource[StreamNumber]     = TRUE;
2154
2155     if(oldSrc == pStreamData &&
2156        This->updateStateBlock->streamStride[StreamNumber] == Stride &&
2157        This->updateStateBlock->streamOffset[StreamNumber] == OffsetInBytes) {
2158        TRACE("Application is setting the old values over, nothing to do\n");
2159        return WINED3D_OK;
2160     }
2161
2162     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
2163     if (pStreamData) {
2164         This->updateStateBlock->streamStride[StreamNumber]     = Stride;
2165         This->updateStateBlock->streamOffset[StreamNumber]     = OffsetInBytes;
2166     }
2167
2168     /* Handle recording of state blocks */
2169     if (This->isRecordingState) {
2170         TRACE("Recording... not performing anything\n");
2171         return WINED3D_OK;
2172     }
2173
2174     /* Need to do a getParent and pass the reffs up */
2175     /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2176     which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2177     so for now, just count internally   */
2178     if (pStreamData != NULL) {
2179         IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2180         InterlockedIncrement(&vbImpl->bindCount);
2181     }
2182     if (oldSrc != NULL) {
2183         InterlockedDecrement(&((IWineD3DVertexBufferImpl *) oldSrc)->bindCount);
2184     }
2185
2186     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2187
2188     return WINED3D_OK;
2189 }
2190
2191 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2192     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2193
2194     TRACE("(%p) : StreamNo: %u, Stream (%p), Offset %u, Stride %u\n", This, StreamNumber,
2195            This->stateBlock->streamSource[StreamNumber],
2196            This->stateBlock->streamOffset[StreamNumber],
2197            This->stateBlock->streamStride[StreamNumber]);
2198
2199     if (StreamNumber >= MAX_STREAMS) {
2200         WARN("Stream out of range %d\n", StreamNumber);
2201         return WINED3DERR_INVALIDCALL;
2202     }
2203     *pStream = This->stateBlock->streamSource[StreamNumber];
2204     *pStride = This->stateBlock->streamStride[StreamNumber];
2205     if (pOffset) {
2206         *pOffset = This->stateBlock->streamOffset[StreamNumber];
2207     }
2208
2209     if (*pStream != NULL) {
2210         IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2211     }
2212     return WINED3D_OK;
2213 }
2214
2215 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
2216     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2217     UINT oldFlags = This->updateStateBlock->streamFlags[StreamNumber];
2218     UINT oldFreq = This->updateStateBlock->streamFreq[StreamNumber];
2219
2220     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2221     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
2222
2223     This->updateStateBlock->changed.streamFreq[StreamNumber]  = TRUE;
2224     This->updateStateBlock->set.streamFreq[StreamNumber]      = TRUE;
2225     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
2226
2227     if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq ||
2228        This->updateStateBlock->streamFlags[StreamNumber] != oldFlags) {
2229         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2230     }
2231
2232     return WINED3D_OK;
2233 }
2234
2235 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
2236     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2237
2238     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2239     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2240
2241     TRACE("(%p) : returning %d\n", This, *Divider);
2242
2243     return WINED3D_OK;
2244 }
2245
2246 /*****
2247  * Get / Set & Multiply Transform
2248  *****/
2249 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2250     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2251
2252     /* Most of this routine, comments included copied from ddraw tree initially: */
2253     TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2254
2255     /* Handle recording of state blocks */
2256     if (This->isRecordingState) {
2257         TRACE("Recording... not performing anything\n");
2258         This->updateStateBlock->changed.transform[d3dts] = TRUE;
2259         This->updateStateBlock->set.transform[d3dts]     = TRUE;
2260         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2261         return WINED3D_OK;
2262     }
2263
2264     /*
2265      * If the new matrix is the same as the current one,
2266      * we cut off any further processing. this seems to be a reasonable
2267      * optimization because as was noticed, some apps (warcraft3 for example)
2268      * tend towards setting the same matrix repeatedly for some reason.
2269      *
2270      * From here on we assume that the new matrix is different, wherever it matters.
2271      */
2272     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2273         TRACE("The app is setting the same matrix over again\n");
2274         return WINED3D_OK;
2275     } else {
2276         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2277     }
2278
2279     /*
2280        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2281        where ViewMat = Camera space, WorldMat = world space.
2282
2283        In OpenGL, camera and world space is combined into GL_MODELVIEW
2284        matrix.  The Projection matrix stay projection matrix.
2285      */
2286
2287     /* Capture the times we can just ignore the change for now */
2288     if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2289         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2290         /* Handled by the state manager */
2291     }
2292
2293     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2294     return WINED3D_OK;
2295
2296 }
2297 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2298     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2299     TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2300     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2301     return WINED3D_OK;
2302 }
2303
2304 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2305     WINED3DMATRIX *mat = NULL;
2306     WINED3DMATRIX temp;
2307
2308     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2309      * below means it will be recorded in a state block change, but it
2310      * works regardless where it is recorded.
2311      * If this is found to be wrong, change to StateBlock.
2312      */
2313     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2314     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2315
2316     if (State < HIGHEST_TRANSFORMSTATE)
2317     {
2318         mat = &This->updateStateBlock->transforms[State];
2319     } else {
2320         FIXME("Unhandled transform state!!\n");
2321     }
2322
2323     multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2324
2325     /* Apply change via set transform - will reapply to eg. lights this way */
2326     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2327 }
2328
2329 /*****
2330  * Get / Set Light
2331  *****/
2332 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2333    you can reference any indexes you want as long as that number max are enabled at any
2334    one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2335    However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2336    but when recording, just build a chain pretty much of commands to be replayed.                  */
2337
2338 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2339     float rho;
2340     PLIGHTINFOEL *object = NULL;
2341     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2342     struct list *e;
2343
2344     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2345     TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This, Index, pLight, Hi);
2346
2347     /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2348      * the gl driver.
2349      */
2350     if(!pLight) {
2351         WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2352         return WINED3DERR_INVALIDCALL;
2353     }
2354
2355     switch(pLight->Type) {
2356         case WINED3DLIGHT_POINT:
2357         case WINED3DLIGHT_SPOT:
2358         case WINED3DLIGHT_PARALLELPOINT:
2359         case WINED3DLIGHT_GLSPOT:
2360             /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2361              * most wanted
2362              */
2363             if(pLight->Attenuation0 < 0.0 || pLight->Attenuation1 < 0.0 || pLight->Attenuation2 < 0.0) {
2364                 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2365                 return WINED3DERR_INVALIDCALL;
2366             }
2367             break;
2368
2369         case WINED3DLIGHT_DIRECTIONAL:
2370             /* Ignores attenuation */
2371             break;
2372
2373         default:
2374         WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2375         return WINED3DERR_INVALIDCALL;
2376     }
2377
2378     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2379         object = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2380         if(object->OriginalIndex == Index) break;
2381         object = NULL;
2382     }
2383
2384     if(!object) {
2385         TRACE("Adding new light\n");
2386         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2387         if(!object) {
2388             ERR("Out of memory error when allocating a light\n");
2389             return E_OUTOFMEMORY;
2390         }
2391         list_add_head(&This->updateStateBlock->lightMap[Hi], &object->entry);
2392         object->glIndex = -1;
2393         object->OriginalIndex = Index;
2394         object->changed = TRUE;
2395     }
2396
2397     /* Initialize the object */
2398     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,
2399           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2400           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2401           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2402     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2403           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2404     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2405
2406     /* Save away the information */
2407     memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2408
2409     switch (pLight->Type) {
2410     case WINED3DLIGHT_POINT:
2411         /* Position */
2412         object->lightPosn[0] = pLight->Position.x;
2413         object->lightPosn[1] = pLight->Position.y;
2414         object->lightPosn[2] = pLight->Position.z;
2415         object->lightPosn[3] = 1.0f;
2416         object->cutoff = 180.0f;
2417         /* FIXME: Range */
2418         break;
2419
2420     case WINED3DLIGHT_DIRECTIONAL:
2421         /* Direction */
2422         object->lightPosn[0] = -pLight->Direction.x;
2423         object->lightPosn[1] = -pLight->Direction.y;
2424         object->lightPosn[2] = -pLight->Direction.z;
2425         object->lightPosn[3] = 0.0;
2426         object->exponent     = 0.0f;
2427         object->cutoff       = 180.0f;
2428         break;
2429
2430     case WINED3DLIGHT_SPOT:
2431         /* Position */
2432         object->lightPosn[0] = pLight->Position.x;
2433         object->lightPosn[1] = pLight->Position.y;
2434         object->lightPosn[2] = pLight->Position.z;
2435         object->lightPosn[3] = 1.0;
2436
2437         /* Direction */
2438         object->lightDirn[0] = pLight->Direction.x;
2439         object->lightDirn[1] = pLight->Direction.y;
2440         object->lightDirn[2] = pLight->Direction.z;
2441         object->lightDirn[3] = 1.0;
2442
2443         /*
2444          * opengl-ish and d3d-ish spot lights use too different models for the
2445          * light "intensity" as a function of the angle towards the main light direction,
2446          * so we only can approximate very roughly.
2447          * however spot lights are rather rarely used in games (if ever used at all).
2448          * furthermore if still used, probably nobody pays attention to such details.
2449          */
2450         if (pLight->Falloff == 0) {
2451             rho = 6.28f;
2452         } else {
2453             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2454         }
2455         if (rho < 0.0001) rho = 0.0001f;
2456         object->exponent = -0.3/log(cos(rho/2));
2457         if (object->exponent > 128.0) {
2458                 object->exponent = 128.0;
2459         }
2460         object->cutoff = pLight->Phi*90/M_PI;
2461
2462         /* FIXME: Range */
2463         break;
2464
2465     default:
2466         FIXME("Unrecognized light type %d\n", pLight->Type);
2467     }
2468
2469     /* Update the live definitions if the light is currently assigned a glIndex */
2470     if (object->glIndex != -1 && !This->isRecordingState) {
2471         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(object->glIndex));
2472     }
2473     return WINED3D_OK;
2474 }
2475
2476 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2477     PLIGHTINFOEL *lightInfo = NULL;
2478     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2479     DWORD Hi = LIGHTMAP_HASHFUNC(Index);
2480     struct list *e;
2481     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2482
2483     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2484         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2485         if(lightInfo->OriginalIndex == Index) break;
2486         lightInfo = NULL;
2487     }
2488
2489     if (lightInfo == NULL) {
2490         TRACE("Light information requested but light not defined\n");
2491         return WINED3DERR_INVALIDCALL;
2492     }
2493
2494     memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2495     return WINED3D_OK;
2496 }
2497
2498 /*****
2499  * Get / Set Light Enable
2500  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2501  *****/
2502 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2503     PLIGHTINFOEL *lightInfo = NULL;
2504     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2505     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2506     struct list *e;
2507     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2508
2509     /* Tests show true = 128...not clear why */
2510     Enable = Enable? 128: 0;
2511
2512     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2513         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2514         if(lightInfo->OriginalIndex == Index) break;
2515         lightInfo = NULL;
2516     }
2517     TRACE("Found light: %p\n", lightInfo);
2518
2519     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2520     if (lightInfo == NULL) {
2521
2522         TRACE("Light enabled requested but light not defined, so defining one!\n");
2523         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2524
2525         /* Search for it again! Should be fairly quick as near head of list */
2526         LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2527             lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2528             if(lightInfo->OriginalIndex == Index) break;
2529             lightInfo = NULL;
2530         }
2531         if (lightInfo == NULL) {
2532             FIXME("Adding default lights has failed dismally\n");
2533             return WINED3DERR_INVALIDCALL;
2534         }
2535     }
2536
2537     lightInfo->enabledChanged = TRUE;
2538     if(!Enable) {
2539         if(lightInfo->glIndex != -1) {
2540             if(!This->isRecordingState) {
2541                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(lightInfo->glIndex));
2542             }
2543
2544             This->stateBlock->activeLights[lightInfo->glIndex] = NULL;
2545             lightInfo->glIndex = -1;
2546         } else {
2547             TRACE("Light already disabled, nothing to do\n");
2548         }
2549     } else {
2550         if (lightInfo->glIndex != -1) {
2551             /* nop */
2552             TRACE("Nothing to do as light was enabled\n");
2553         } else {
2554             int i;
2555             /* Find a free gl light */
2556             for(i = 0; i < This->maxConcurrentLights; i++) {
2557                 if(This->stateBlock->activeLights[i] == NULL) {
2558                     This->stateBlock->activeLights[i] = lightInfo;
2559                     lightInfo->glIndex = i;
2560                     break;
2561                 }
2562             }
2563             if(lightInfo->glIndex == -1) {
2564                 ERR("Too many concurrently active lights\n");
2565                 return WINED3DERR_INVALIDCALL;
2566             }
2567
2568             /* i == lightInfo->glIndex */
2569             if(!This->isRecordingState) {
2570                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i));
2571             }
2572         }
2573     }
2574
2575     return WINED3D_OK;
2576 }
2577
2578 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2579
2580     PLIGHTINFOEL *lightInfo = NULL;
2581     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2582     struct list *e;
2583     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2584     TRACE("(%p) : for idx(%d)\n", This, Index);
2585
2586     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2587         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2588         if(lightInfo->OriginalIndex == Index) break;
2589         lightInfo = NULL;
2590     }
2591
2592     if (lightInfo == NULL) {
2593         TRACE("Light enabled state requested but light not defined\n");
2594         return WINED3DERR_INVALIDCALL;
2595     }
2596     /* true is 128 according to SetLightEnable */
2597     *pEnable = lightInfo->glIndex != -1 ? 128 : 0;
2598     return WINED3D_OK;
2599 }
2600
2601 /*****
2602  * Get / Set Clip Planes
2603  *****/
2604 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2605     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2606     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
2607
2608     /* Validate Index */
2609     if (Index >= GL_LIMITS(clipplanes)) {
2610         TRACE("Application has requested clipplane this device doesn't support\n");
2611         return WINED3DERR_INVALIDCALL;
2612     }
2613
2614     This->updateStateBlock->changed.clipplane[Index] = TRUE;
2615     This->updateStateBlock->set.clipplane[Index] = TRUE;
2616
2617     if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
2618        This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
2619        This->updateStateBlock->clipplane[Index][2] == pPlane[2] &&
2620        This->updateStateBlock->clipplane[Index][3] == pPlane[3]) {
2621         TRACE("Application is setting old values over, nothing to do\n");
2622         return WINED3D_OK;
2623     }
2624
2625     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2626     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2627     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2628     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2629
2630     /* Handle recording of state blocks */
2631     if (This->isRecordingState) {
2632         TRACE("Recording... not performing anything\n");
2633         return WINED3D_OK;
2634     }
2635
2636     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_CLIPPLANE(Index));
2637
2638     return WINED3D_OK;
2639 }
2640
2641 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2642     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2643     TRACE("(%p) : for idx %d\n", This, Index);
2644
2645     /* Validate Index */
2646     if (Index >= GL_LIMITS(clipplanes)) {
2647         TRACE("Application has requested clipplane this device doesn't support\n");
2648         return WINED3DERR_INVALIDCALL;
2649     }
2650
2651     pPlane[0] = This->stateBlock->clipplane[Index][0];
2652     pPlane[1] = This->stateBlock->clipplane[Index][1];
2653     pPlane[2] = This->stateBlock->clipplane[Index][2];
2654     pPlane[3] = This->stateBlock->clipplane[Index][3];
2655     return WINED3D_OK;
2656 }
2657
2658 /*****
2659  * Get / Set Clip Plane Status
2660  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2661  *****/
2662 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2663     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2664     FIXME("(%p) : stub\n", This);
2665     if (NULL == pClipStatus) {
2666       return WINED3DERR_INVALIDCALL;
2667     }
2668     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2669     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2670     return WINED3D_OK;
2671 }
2672
2673 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2674     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2675     FIXME("(%p) : stub\n", This);
2676     if (NULL == pClipStatus) {
2677       return WINED3DERR_INVALIDCALL;
2678     }
2679     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2680     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2681     return WINED3D_OK;
2682 }
2683
2684 /*****
2685  * Get / Set Material
2686  *****/
2687 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2688     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2689
2690     This->updateStateBlock->changed.material = TRUE;
2691     This->updateStateBlock->set.material = TRUE;
2692     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2693
2694     /* Handle recording of state blocks */
2695     if (This->isRecordingState) {
2696         TRACE("Recording... not performing anything\n");
2697         return WINED3D_OK;
2698     }
2699
2700     ENTER_GL();
2701     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2702         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2703     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2704         pMaterial->Ambient.b, pMaterial->Ambient.a);
2705     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2706         pMaterial->Specular.b, pMaterial->Specular.a);
2707     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2708         pMaterial->Emissive.b, pMaterial->Emissive.a);
2709     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2710
2711     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2712     checkGLcall("glMaterialfv(GL_AMBIENT)");
2713     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2714     checkGLcall("glMaterialfv(GL_DIFFUSE)");
2715
2716     /* Only change material color if specular is enabled, otherwise it is set to black */
2717     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2718        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2719        checkGLcall("glMaterialfv(GL_SPECULAR");
2720     } else {
2721        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2722        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2723        checkGLcall("glMaterialfv(GL_SPECULAR");
2724     }
2725     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2726     checkGLcall("glMaterialfv(GL_EMISSION)");
2727     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2728     checkGLcall("glMaterialf(GL_SHININESS");
2729
2730     LEAVE_GL();
2731     return WINED3D_OK;
2732 }
2733
2734 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2735     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2736     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2737     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2738         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2739     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2740         pMaterial->Ambient.b, pMaterial->Ambient.a);
2741     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2742         pMaterial->Specular.b, pMaterial->Specular.a);
2743     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2744         pMaterial->Emissive.b, pMaterial->Emissive.a);
2745     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2746
2747     return WINED3D_OK;
2748 }
2749
2750 /*****
2751  * Get / Set Indices
2752  *****/
2753 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData) {
2754     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
2755     IWineD3DIndexBuffer *oldIdxs;
2756
2757     TRACE("(%p) : Setting to %p\n", This, pIndexData);
2758     oldIdxs = This->updateStateBlock->pIndexData;
2759
2760     This->updateStateBlock->changed.indices = TRUE;
2761     This->updateStateBlock->set.indices = TRUE;
2762     This->updateStateBlock->pIndexData = pIndexData;
2763
2764     /* Handle recording of state blocks */
2765     if (This->isRecordingState) {
2766         TRACE("Recording... not performing anything\n");
2767         return WINED3D_OK;
2768     }
2769
2770     if(oldIdxs != pIndexData) {
2771         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
2772     }
2773     return WINED3D_OK;
2774 }
2775
2776 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData) {
2777     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2778
2779     *ppIndexData = This->stateBlock->pIndexData;
2780
2781     /* up ref count on ppindexdata */
2782     if (*ppIndexData) {
2783         IWineD3DIndexBuffer_AddRef(*ppIndexData);
2784         TRACE("(%p) index data set to %p\n", This, ppIndexData);
2785     }else{
2786         TRACE("(%p) No index data set\n", This);
2787     }
2788     TRACE("Returning %p\n", *ppIndexData);
2789
2790     return WINED3D_OK;
2791 }
2792
2793 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2794 static HRESULT WINAPI IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice *iface, UINT BaseIndex) {
2795     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2796     TRACE("(%p)->(%d)\n", This, BaseIndex);
2797
2798     if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
2799         TRACE("Application is setting the old value over, nothing to do\n");
2800         return WINED3D_OK;
2801     }
2802
2803     This->updateStateBlock->baseVertexIndex = BaseIndex;
2804
2805     if (This->isRecordingState) {
2806         TRACE("Recording... not performing anything\n");
2807         return WINED3D_OK;
2808     }
2809     /* The base vertex index affects the stream sources */
2810     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2811     return WINED3D_OK;
2812 }
2813
2814 static HRESULT WINAPI IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice *iface, UINT* base_index) {
2815     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2816     TRACE("(%p) : base_index %p\n", This, base_index);
2817
2818     *base_index = This->stateBlock->baseVertexIndex;
2819
2820     TRACE("Returning %u\n", *base_index);
2821
2822     return WINED3D_OK;
2823 }
2824
2825 /*****
2826  * Get / Set Viewports
2827  *****/
2828 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2829     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2830
2831     TRACE("(%p)\n", This);
2832     This->updateStateBlock->changed.viewport = TRUE;
2833     This->updateStateBlock->set.viewport = TRUE;
2834     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2835
2836     /* Handle recording of state blocks */
2837     if (This->isRecordingState) {
2838         TRACE("Recording... not performing anything\n");
2839         return WINED3D_OK;
2840     }
2841
2842     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
2843           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2844
2845     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
2846     return WINED3D_OK;
2847
2848 }
2849
2850 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2851     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2852     TRACE("(%p)\n", This);
2853     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2854     return WINED3D_OK;
2855 }
2856
2857 /*****
2858  * Get / Set Render States
2859  * TODO: Verify against dx9 definitions
2860  *****/
2861 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
2862
2863     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
2864     DWORD oldValue = This->stateBlock->renderState[State];
2865
2866     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
2867
2868     This->updateStateBlock->changed.renderState[State] = TRUE;
2869     This->updateStateBlock->set.renderState[State] = TRUE;
2870     This->updateStateBlock->renderState[State] = Value;
2871
2872     /* Handle recording of state blocks */
2873     if (This->isRecordingState) {
2874         TRACE("Recording... not performing anything\n");
2875         return WINED3D_OK;
2876     }
2877
2878     /* Compared here and not before the assignment to allow proper stateblock recording */
2879     if(Value == oldValue) {
2880         TRACE("Application is setting the old value over, nothing to do\n");
2881     } else {
2882         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
2883     }
2884
2885     return WINED3D_OK;
2886 }
2887
2888 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
2889     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2890     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
2891     *pValue = This->stateBlock->renderState[State];
2892     return WINED3D_OK;
2893 }
2894
2895 /*****
2896  * Get / Set Sampler States
2897  * TODO: Verify against dx9 definitions
2898  *****/
2899
2900 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
2901     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2902     DWORD oldValue = This->stateBlock->samplerState[Sampler][Type];
2903
2904     /**
2905     * SetSampler is designed to allow for more than the standard up to 8 textures
2906     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
2907     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
2908     *
2909     * http://developer.nvidia.com/object/General_FAQ.html#t6
2910     *
2911     * There are two new settings for GForce
2912     * the sampler one:
2913     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
2914     * and the texture one:
2915     * GL_MAX_TEXTURE_COORDS_ARB.
2916     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
2917      ******************/
2918
2919     TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
2920         debug_d3dsamplerstate(Type), Type, Value);
2921     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
2922     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
2923     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
2924
2925     /* Handle recording of state blocks */
2926     if (This->isRecordingState) {
2927         TRACE("Recording... not performing anything\n");
2928         return WINED3D_OK;
2929     }
2930
2931     if(oldValue == Value) {
2932         TRACE("Application is setting the old value over, nothing to do\n");
2933         return WINED3D_OK;
2934     }
2935
2936     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
2937
2938     return WINED3D_OK;
2939 }
2940
2941 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
2942     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2943     *Value = This->stateBlock->samplerState[Sampler][Type];
2944     TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
2945
2946     return WINED3D_OK;
2947 }
2948
2949 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
2950     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2951
2952     This->updateStateBlock->set.scissorRect = TRUE;
2953     This->updateStateBlock->changed.scissorRect = TRUE;
2954     if(EqualRect(&This->updateStateBlock->scissorRect, pRect)) {
2955         TRACE("App is setting the old scissor rectangle over, nothing to do\n");
2956         return WINED3D_OK;
2957     }
2958     CopyRect(&This->updateStateBlock->scissorRect, pRect);
2959
2960     if(This->isRecordingState) {
2961         TRACE("Recording... not performing anything\n");
2962         return WINED3D_OK;
2963     }
2964
2965     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
2966
2967     return WINED3D_OK;
2968 }
2969
2970 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
2971     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2972
2973     memcpy(pRect, &This->updateStateBlock->scissorRect, sizeof(pRect));
2974     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2975     return WINED3D_OK;
2976 }
2977
2978 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
2979     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2980     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
2981
2982     TRACE("(%p) : pDecl=%p\n", This, pDecl);
2983
2984     This->updateStateBlock->vertexDecl = pDecl;
2985     This->updateStateBlock->changed.vertexDecl = TRUE;
2986     This->updateStateBlock->set.vertexDecl = TRUE;
2987
2988     if (This->isRecordingState) {
2989         TRACE("Recording... not performing anything\n");
2990         return WINED3D_OK;
2991     } else if(pDecl == oldDecl) {
2992         /* Checked after the assignment to allow proper stateblock recording */
2993         TRACE("Application is setting the old declaration over, nothing to do\n");
2994         return WINED3D_OK;
2995     }
2996
2997     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
2998     return WINED3D_OK;
2999 }
3000
3001 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3002     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3003
3004     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3005
3006     *ppDecl = This->stateBlock->vertexDecl;
3007     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3008     return WINED3D_OK;
3009 }
3010
3011 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3012     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3013     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3014
3015     This->updateStateBlock->vertexShader         = pShader;
3016     This->updateStateBlock->changed.vertexShader = TRUE;
3017     This->updateStateBlock->set.vertexShader     = TRUE;
3018
3019     if (This->isRecordingState) {
3020         TRACE("Recording... not performing anything\n");
3021         return WINED3D_OK;
3022     } else if(oldShader == pShader) {
3023         /* Checked here to allow proper stateblock recording */
3024         TRACE("App is setting the old shader over, nothing to do\n");
3025         return WINED3D_OK;
3026     }
3027
3028     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3029
3030     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
3031
3032     return WINED3D_OK;
3033 }
3034
3035 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3036     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3037
3038     if (NULL == ppShader) {
3039         return WINED3DERR_INVALIDCALL;
3040     }
3041     *ppShader = This->stateBlock->vertexShader;
3042     if( NULL != *ppShader)
3043         IWineD3DVertexShader_AddRef(*ppShader);
3044
3045     TRACE("(%p) : returning %p\n", This, *ppShader);
3046     return WINED3D_OK;
3047 }
3048
3049 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
3050     IWineD3DDevice *iface,
3051     UINT start,
3052     CONST BOOL *srcData,
3053     UINT count) {
3054
3055     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3056     int i, cnt = min(count, MAX_CONST_B - start);
3057
3058     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3059             iface, srcData, start, count);
3060
3061     if (srcData == NULL || cnt < 0)
3062         return WINED3DERR_INVALIDCALL;
3063
3064     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3065     for (i = 0; i < cnt; i++)
3066         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3067
3068     for (i = start; i < cnt + start; ++i) {
3069         This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
3070         This->updateStateBlock->set.vertexShaderConstantsB[i]     = TRUE;
3071     }
3072
3073     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3074
3075     return WINED3D_OK;
3076 }
3077
3078 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
3079     IWineD3DDevice *iface,
3080     UINT start,
3081     BOOL *dstData,
3082     UINT count) {
3083
3084     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3085     int cnt = min(count, MAX_CONST_B - start);
3086
3087     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3088             iface, dstData, start, count);
3089
3090     if (dstData == NULL || cnt < 0)
3091         return WINED3DERR_INVALIDCALL;
3092
3093     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
3094     return WINED3D_OK;
3095 }
3096
3097 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
3098     IWineD3DDevice *iface,
3099     UINT start,
3100     CONST int *srcData,
3101     UINT count) {
3102
3103     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3104     int i, cnt = min(count, MAX_CONST_I - start);
3105
3106     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3107             iface, srcData, start, count);
3108
3109     if (srcData == NULL || cnt < 0)
3110         return WINED3DERR_INVALIDCALL;
3111
3112     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3113     for (i = 0; i < cnt; i++)
3114         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3115            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3116
3117     for (i = start; i < cnt + start; ++i) {
3118         This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
3119         This->updateStateBlock->set.vertexShaderConstantsI[i]     = TRUE;
3120     }
3121
3122     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3123
3124     return WINED3D_OK;
3125 }
3126
3127 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
3128     IWineD3DDevice *iface,
3129     UINT start,
3130     int *dstData,
3131     UINT count) {
3132
3133     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3134     int cnt = min(count, MAX_CONST_I - start);
3135
3136     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3137             iface, dstData, start, count);
3138
3139     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
3140         return WINED3DERR_INVALIDCALL;
3141
3142     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3143     return WINED3D_OK;
3144 }
3145
3146 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3147     IWineD3DDevice *iface,
3148     UINT start,
3149     CONST float *srcData,
3150     UINT count) {
3151
3152     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3153     int i;
3154
3155     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3156             iface, srcData, start, count);
3157
3158     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3159     if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
3160         return WINED3DERR_INVALIDCALL;
3161
3162     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3163     if(TRACE_ON(d3d)) {
3164         for (i = 0; i < count; i++)
3165             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3166                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3167     }
3168
3169     for (i = start; i < count + start; ++i) {
3170         if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
3171             constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_vconstantsF), constants_entry, entry);
3172             if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
3173                 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
3174                 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
3175             }
3176             ptr->idx[ptr->count++] = i;
3177             This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
3178         }
3179         This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
3180     }
3181
3182     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3183
3184     return WINED3D_OK;
3185 }
3186
3187 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3188     IWineD3DDevice *iface,
3189     UINT start,
3190     float *dstData,
3191     UINT count) {
3192
3193     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3194     int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3195
3196     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3197             iface, dstData, start, count);
3198
3199     if (dstData == NULL || cnt < 0)
3200         return WINED3DERR_INVALIDCALL;
3201
3202     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3203     return WINED3D_OK;
3204 }
3205
3206 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3207     DWORD i;
3208     for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
3209         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3210     }
3211 }
3212
3213 static void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3214     DWORD i, tex;
3215     /* This code can assume that GL_NV_register_combiners are supported, otherwise
3216      * it is never called.
3217      *
3218      * Rules are:
3219      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3220      * that would be really messy and require shader recompilation
3221      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3222      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3223      * -> Whith a 1:1 mapping oneToOneTexUnitMap is set to avoid checking MAX_SAMPLERS array
3224      * entries to make pixel shaders cheaper. MAX_SAMPLERS will be 128 in dx10
3225      */
3226     if(This->stateBlock->pixelShader || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) {
3227         if(This->oneToOneTexUnitMap) {
3228             TRACE("Not touching 1:1 map\n");
3229             return;
3230         }
3231         TRACE("Restoring 1:1 texture unit mapping\n");
3232         /* Restore a 1:1 mapping */
3233         for(i = 0; i < MAX_SAMPLERS; i++) {
3234             if(This->texUnitMap[i] != i) {
3235                 This->texUnitMap[i] = i;
3236                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3237                 markTextureStagesDirty(This, i);
3238             }
3239         }
3240         This->oneToOneTexUnitMap = TRUE;
3241         return;
3242     } else {
3243         /* No pixel shader, and we do not have enough texture units available. Try to skip NULL textures
3244          * First, see if we can succeed at all
3245          */
3246         tex = 0;
3247         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3248             if(This->stateBlock->textures[i] == NULL) tex++;
3249         }
3250
3251         if(GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) {
3252             FIXME("Too many bound textures to support the combiner settings\n");
3253             return;
3254         }
3255
3256         /* Now work out the mapping */
3257         tex = 0;
3258         This->oneToOneTexUnitMap = FALSE;
3259         WARN("Non 1:1 mapping UNTESTED!\n");
3260         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3261             /* Skip NULL textures */
3262             if (!This->stateBlock->textures[i]) {
3263                 /* Map to -1, so the check below doesn't fail if a non-NULL
3264                  * texture is set on this stage */
3265                 TRACE("Mapping texture stage %d to -1\n", i);
3266                 This->texUnitMap[i] = -1;
3267
3268                 continue;
3269             }
3270
3271             TRACE("Mapping texture stage %d to unit %d\n", i, tex);
3272             if(This->texUnitMap[i] != tex) {
3273                 This->texUnitMap[i] = tex;
3274                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3275                 markTextureStagesDirty(This, i);
3276             }
3277
3278             ++tex;
3279         }
3280     }
3281 }
3282
3283 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3284     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3285     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3286     This->updateStateBlock->pixelShader         = pShader;
3287     This->updateStateBlock->changed.pixelShader = TRUE;
3288     This->updateStateBlock->set.pixelShader     = TRUE;
3289
3290     /* Handle recording of state blocks */
3291     if (This->isRecordingState) {
3292         TRACE("Recording... not performing anything\n");
3293     }
3294
3295     if (This->isRecordingState) {
3296         TRACE("Recording... not performing anything\n");
3297         return WINED3D_OK;
3298     }
3299
3300     if(pShader == oldShader) {
3301         TRACE("App is setting the old pixel shader over, nothing to do\n");
3302         return WINED3D_OK;
3303     }
3304
3305     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3306     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3307
3308     /* Rebuild the texture unit mapping if nvrc's are supported */
3309     if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3310         IWineD3DDeviceImpl_FindTexUnitMap(This);
3311     }
3312
3313     return WINED3D_OK;
3314 }
3315
3316 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3317     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3318
3319     if (NULL == ppShader) {
3320         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3321         return WINED3DERR_INVALIDCALL;
3322     }
3323
3324     *ppShader =  This->stateBlock->pixelShader;
3325     if (NULL != *ppShader) {
3326         IWineD3DPixelShader_AddRef(*ppShader);
3327     }
3328     TRACE("(%p) : returning %p\n", This, *ppShader);
3329     return WINED3D_OK;
3330 }
3331
3332 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3333     IWineD3DDevice *iface,
3334     UINT start,
3335     CONST BOOL *srcData,
3336     UINT count) {
3337
3338     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3339     int i, cnt = min(count, MAX_CONST_B - start);
3340
3341     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3342             iface, srcData, start, count);
3343
3344     if (srcData == NULL || cnt < 0)
3345         return WINED3DERR_INVALIDCALL;
3346
3347     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3348     for (i = 0; i < cnt; i++)
3349         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3350
3351     for (i = start; i < cnt + start; ++i) {
3352         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3353         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
3354     }
3355
3356     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3357
3358     return WINED3D_OK;
3359 }
3360
3361 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3362     IWineD3DDevice *iface,
3363     UINT start,
3364     BOOL *dstData,
3365     UINT count) {
3366
3367     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3368     int cnt = min(count, MAX_CONST_B - start);
3369
3370     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3371             iface, dstData, start, count);
3372
3373     if (dstData == NULL || cnt < 0)
3374         return WINED3DERR_INVALIDCALL;
3375
3376     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3377     return WINED3D_OK;
3378 }
3379
3380 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3381     IWineD3DDevice *iface,
3382     UINT start,
3383     CONST int *srcData,
3384     UINT count) {
3385
3386     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3387     int i, cnt = min(count, MAX_CONST_I - start);
3388
3389     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3390             iface, srcData, start, count);
3391
3392     if (srcData == NULL || cnt < 0)
3393         return WINED3DERR_INVALIDCALL;
3394
3395     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3396     for (i = 0; i < cnt; i++)
3397         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3398            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3399
3400     for (i = start; i < cnt + start; ++i) {
3401         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3402         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
3403     }
3404
3405     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3406
3407     return WINED3D_OK;
3408 }
3409
3410 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3411     IWineD3DDevice *iface,
3412     UINT start,
3413     int *dstData,
3414     UINT count) {
3415
3416     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3417     int cnt = min(count, MAX_CONST_I - start);
3418
3419     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3420             iface, dstData, start, count);
3421
3422     if (dstData == NULL || cnt < 0)
3423         return WINED3DERR_INVALIDCALL;
3424
3425     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3426     return WINED3D_OK;
3427 }
3428
3429 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3430     IWineD3DDevice *iface,
3431     UINT start,
3432     CONST float *srcData,
3433     UINT count) {
3434
3435     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3436     int i;
3437
3438     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3439             iface, srcData, start, count);
3440
3441     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3442     if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
3443         return WINED3DERR_INVALIDCALL;
3444
3445     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3446     if(TRACE_ON(d3d)) {
3447         for (i = 0; i < count; i++)
3448             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3449                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3450     }
3451
3452     for (i = start; i < count + start; ++i) {
3453         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3454             constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry);
3455             if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
3456                 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
3457                 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3458             }
3459             ptr->idx[ptr->count++] = i;
3460             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3461         }
3462         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3463     }
3464
3465     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3466
3467     return WINED3D_OK;
3468 }
3469
3470 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3471     IWineD3DDevice *iface,
3472     UINT start,
3473     float *dstData,
3474     UINT count) {
3475
3476     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3477     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3478
3479     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3480             iface, dstData, start, count);
3481
3482     if (dstData == NULL || cnt < 0)
3483         return WINED3DERR_INVALIDCALL;
3484
3485     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3486     return WINED3D_OK;
3487 }
3488
3489 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3490 static HRESULT
3491 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3492     char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
3493     unsigned int i;
3494     DWORD DestFVF = dest->fvf;
3495     WINED3DVIEWPORT vp;
3496     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3497     BOOL doClip;
3498     int numTextures;
3499
3500     if (lpStrideData->u.s.normal.lpData) {
3501         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3502     }
3503
3504     if (lpStrideData->u.s.position.lpData == NULL) {
3505         ERR("Source has no position mask\n");
3506         return WINED3DERR_INVALIDCALL;
3507     }
3508
3509     /* We might access VBOs from this code, so hold the lock */
3510     ENTER_GL();
3511
3512     if (dest->resource.allocatedMemory == NULL) {
3513         /* This may happen if we do direct locking into a vbo. Unlikely,
3514          * but theoretically possible(ddraw processvertices test)
3515          */
3516         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3517         if(!dest->resource.allocatedMemory) {
3518             LEAVE_GL();
3519             ERR("Out of memory\n");
3520             return E_OUTOFMEMORY;
3521         }
3522         if(dest->vbo) {
3523             void *src;
3524             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3525             checkGLcall("glBindBufferARB");
3526             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3527             if(src) {
3528                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3529             }
3530             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3531             checkGLcall("glUnmapBufferARB");
3532         }
3533     }
3534
3535     /* Get a pointer into the destination vbo(create one if none exists) and
3536      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3537      */
3538     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3539         CreateVBO(dest);
3540     }
3541
3542     if(dest->vbo) {
3543         unsigned char extrabytes = 0;
3544         /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
3545          * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
3546          * this may write 4 extra bytes beyond the area that should be written
3547          */
3548         if(DestFVF == WINED3DFVF_XYZ) extrabytes = 4;
3549         dest_conv_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * get_flexible_vertex_size(DestFVF) + extrabytes);
3550         if(!dest_conv_addr) {
3551             ERR("Out of memory\n");
3552             /* Continue without storing converted vertices */
3553         }
3554         dest_conv = dest_conv_addr;
3555     }
3556
3557     /* Should I clip?
3558      * a) WINED3DRS_CLIPPING is enabled
3559      * b) WINED3DVOP_CLIP is passed
3560      */
3561     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3562         static BOOL warned = FALSE;
3563         /*
3564          * The clipping code is not quite correct. Some things need
3565          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3566          * so disable clipping for now.
3567          * (The graphics in Half-Life are broken, and my processvertices
3568          *  test crashes with IDirect3DDevice3)
3569         doClip = TRUE;
3570          */
3571         doClip = FALSE;
3572         if(!warned) {
3573            warned = TRUE;
3574            FIXME("Clipping is broken and disabled for now\n");
3575         }
3576     } else doClip = FALSE;
3577     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3578
3579     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3580                                  WINED3DTS_VIEW,
3581                                  &view_mat);
3582     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3583                                  WINED3DTS_PROJECTION,
3584                                  &proj_mat);
3585     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3586                                  WINED3DTS_WORLDMATRIX(0),
3587                                  &world_mat);
3588
3589     TRACE("View mat:\n");
3590     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);
3591     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);
3592     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);
3593     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);
3594
3595     TRACE("Proj mat:\n");
3596     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);
3597     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);
3598     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);
3599     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);
3600
3601     TRACE("World mat:\n");
3602     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);
3603     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);
3604     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);
3605     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);
3606
3607     /* Get the viewport */
3608     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3609     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3610           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3611
3612     multiply_matrix(&mat,&view_mat,&world_mat);
3613     multiply_matrix(&mat,&proj_mat,&mat);
3614
3615     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3616
3617     for (i = 0; i < dwCount; i+= 1) {
3618         unsigned int tex_index;
3619
3620         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3621              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3622             /* The position first */
3623             float *p =
3624               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3625             float x, y, z, rhw;
3626             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3627
3628             /* Multiplication with world, view and projection matrix */
3629             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);
3630             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);
3631             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);
3632             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);
3633
3634             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3635
3636             /* WARNING: The following things are taken from d3d7 and were not yet checked
3637              * against d3d8 or d3d9!
3638              */
3639
3640             /* Clipping conditions: From
3641              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
3642              *
3643              * A vertex is clipped if it does not match the following requirements
3644              * -rhw < x <= rhw
3645              * -rhw < y <= rhw
3646              *    0 < z <= rhw
3647              *    0 < rhw ( Not in d3d7, but tested in d3d7)
3648              *
3649              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3650              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3651              *
3652              */
3653
3654             if( !doClip ||
3655                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3656                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
3657                   ( rhw > eps ) ) ) {
3658
3659                 /* "Normal" viewport transformation (not clipped)
3660                  * 1) The values are divided by rhw
3661                  * 2) The y axis is negative, so multiply it with -1
3662                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3663                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3664                  * 4) Multiply x with Width/2 and add Width/2
3665                  * 5) The same for the height
3666                  * 6) Add the viewpoint X and Y to the 2D coordinates and
3667                  *    The minimum Z value to z
3668                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3669                  *
3670                  * Well, basically it's simply a linear transformation into viewport
3671                  * coordinates
3672                  */
3673
3674                 x /= rhw;
3675                 y /= rhw;
3676                 z /= rhw;
3677
3678                 y *= -1;
3679
3680                 x *= vp.Width / 2;
3681                 y *= vp.Height / 2;
3682                 z *= vp.MaxZ - vp.MinZ;
3683
3684                 x += vp.Width / 2 + vp.X;
3685                 y += vp.Height / 2 + vp.Y;
3686                 z += vp.MinZ;
3687
3688                 rhw = 1 / rhw;
3689             } else {
3690                 /* That vertex got clipped
3691                  * Contrary to OpenGL it is not dropped completely, it just
3692                  * undergoes a different calculation.
3693                  */
3694                 TRACE("Vertex got clipped\n");
3695                 x += rhw;
3696                 y += rhw;
3697
3698                 x  /= 2;
3699                 y  /= 2;
3700
3701                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3702                  * outside of the main vertex buffer memory. That needs some more
3703                  * investigation...
3704                  */
3705             }
3706
3707             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3708
3709
3710             ( (float *) dest_ptr)[0] = x;
3711             ( (float *) dest_ptr)[1] = y;
3712             ( (float *) dest_ptr)[2] = z;
3713             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3714
3715             dest_ptr += 3 * sizeof(float);
3716
3717             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3718                 dest_ptr += sizeof(float);
3719             }
3720
3721             if(dest_conv) {
3722                 float w = 1 / rhw;
3723                 ( (float *) dest_conv)[0] = x * w;
3724                 ( (float *) dest_conv)[1] = y * w;
3725                 ( (float *) dest_conv)[2] = z * w;
3726                 ( (float *) dest_conv)[3] = w;
3727
3728                 dest_conv += 3 * sizeof(float);
3729
3730                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3731                     dest_conv += sizeof(float);
3732                 }
3733             }
3734         }
3735         if (DestFVF & WINED3DFVF_PSIZE) {
3736             dest_ptr += sizeof(DWORD);
3737             if(dest_conv) dest_conv += sizeof(DWORD);
3738         }
3739         if (DestFVF & WINED3DFVF_NORMAL) {
3740             float *normal =
3741               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
3742             /* AFAIK this should go into the lighting information */
3743             FIXME("Didn't expect the destination to have a normal\n");
3744             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3745             if(dest_conv) {
3746                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3747             }
3748         }
3749
3750         if (DestFVF & WINED3DFVF_DIFFUSE) {
3751             DWORD *color_d = 
3752               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
3753             if(!color_d) {
3754                 static BOOL warned = FALSE;
3755
3756                 if(!warned) {
3757                     ERR("No diffuse color in source, but destination has one\n");
3758                     warned = TRUE;
3759                 }
3760
3761                 *( (DWORD *) dest_ptr) = 0xffffffff;
3762                 dest_ptr += sizeof(DWORD);
3763
3764                 if(dest_conv) {
3765                     *( (DWORD *) dest_conv) = 0xffffffff;
3766                     dest_conv += sizeof(DWORD);
3767                 }
3768             }
3769             else {
3770                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3771                 if(dest_conv) {
3772                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
3773                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3774                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3775                     dest_conv += sizeof(DWORD);
3776                 }
3777             }
3778         }
3779
3780         if (DestFVF & WINED3DFVF_SPECULAR) { 
3781             /* What's the color value in the feedback buffer? */
3782             DWORD *color_s = 
3783               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
3784             if(!color_s) {
3785                 static BOOL warned = FALSE;
3786
3787                 if(!warned) {
3788                     ERR("No specular color in source, but destination has one\n");
3789                     warned = TRUE;
3790                 }
3791
3792                 *( (DWORD *) dest_ptr) = 0xFF000000;
3793                 dest_ptr += sizeof(DWORD);
3794
3795                 if(dest_conv) {
3796                     *( (DWORD *) dest_conv) = 0xFF000000;
3797                     dest_conv += sizeof(DWORD);
3798                 }
3799             }
3800             else {
3801                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3802                 if(dest_conv) {
3803                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
3804                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
3805                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
3806                     dest_conv += sizeof(DWORD);
3807                 }
3808             }
3809         }
3810
3811         for (tex_index = 0; tex_index < numTextures; tex_index++) {
3812             float *tex_coord =
3813               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
3814                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
3815             if(!tex_coord) {
3816                 ERR("No source texture, but destination requests one\n");
3817                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3818                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3819             }
3820             else {
3821                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3822                 if(dest_conv) {
3823                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3824                 }
3825             }
3826         }
3827     }
3828
3829     if(dest_conv) {
3830         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3831         checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
3832         GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
3833                                       dwCount * get_flexible_vertex_size(DestFVF),
3834                                       dest_conv_addr));
3835         checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
3836         HeapFree(GetProcessHeap(), 0, dest_conv_addr);
3837     }
3838
3839     LEAVE_GL();
3840
3841     return WINED3D_OK;
3842 }
3843 #undef copy_and_next
3844
3845 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexDeclaration* pVertexDecl, DWORD Flags) {
3846     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3847     WineDirect3DVertexStridedData strided;
3848     BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP;
3849     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
3850
3851     if(pVertexDecl) {
3852         ERR("Output vertex declaration not implemented yet\n");
3853     }
3854
3855     /* Need any context to write to the vbo. In a non-multithreaded environment a context is there anyway,
3856      * and this call is quite performance critical, so don't call needlessly
3857      */
3858     if(This->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) {
3859         ENTER_GL();
3860         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
3861         LEAVE_GL();
3862     }
3863
3864     /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
3865      * control the streamIsUP flag, thus restore it afterwards.
3866      */
3867     This->stateBlock->streamIsUP = FALSE;
3868     memset(&strided, 0, sizeof(strided));
3869     if(This->stateBlock->vertexDecl) {
3870         primitiveDeclarationConvertToStridedData(iface, FALSE, &strided, &vbo);
3871     } else {
3872         primitiveConvertToStridedData(iface, &strided, &vbo);
3873     }
3874     This->stateBlock->streamIsUP = streamWasUP;
3875
3876     if(vbo || SrcStartIndex) {
3877         unsigned int i;
3878         /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcesVerticse are
3879          * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the strided structure
3880          *
3881          * Also get the start index in, but only loop over all elements if there's something to add at all.
3882          */
3883 #define FIXSRC(type) \
3884         if(strided.u.s.type.VBO) { \
3885             IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[strided.u.s.type.streamNo]; \
3886             strided.u.s.type.VBO = 0; \
3887             strided.u.s.type.lpData = (BYTE *) ((unsigned long) strided.u.s.type.lpData + (unsigned long) vb->resource.allocatedMemory); \
3888             ENTER_GL(); \
3889             GL_EXTCALL(glDeleteBuffersARB(1, &vb->vbo)); \
3890             vb->vbo = 0; \
3891             LEAVE_GL(); \
3892         } \
3893         if(strided.u.s.type.lpData) { \
3894             strided.u.s.type.lpData += strided.u.s.type.dwStride * SrcStartIndex; \
3895         }
3896         FIXSRC(position);
3897         FIXSRC(blendWeights);
3898         FIXSRC(blendMatrixIndices);
3899         FIXSRC(normal);
3900         FIXSRC(pSize);
3901         FIXSRC(diffuse);
3902         FIXSRC(specular);
3903         for(i = 0; i < WINED3DDP_MAXTEXCOORD; i++) {
3904             FIXSRC(texCoords[i]);
3905         }
3906         FIXSRC(position2);
3907         FIXSRC(normal2);
3908         FIXSRC(tangent);
3909         FIXSRC(binormal);
3910         FIXSRC(tessFactor);
3911         FIXSRC(fog);
3912         FIXSRC(depth);
3913         FIXSRC(sample);
3914 #undef FIXSRC
3915     }
3916
3917     return process_vertices_strided(This, DestIndex, VertexCount, &strided, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
3918 }
3919
3920 /*****
3921  * Get / Set Texture Stage States
3922  * TODO: Verify against dx9 definitions
3923  *****/
3924 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3925     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3926     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
3927
3928     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3929
3930     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3931
3932     if (Stage >= MAX_TEXTURES) {
3933         WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring\n", Stage, MAX_TEXTURES - 1);
3934         return WINED3D_OK;
3935     }
3936
3937     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3938     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
3939     This->updateStateBlock->textureState[Stage][Type]         = Value;
3940
3941     if (This->isRecordingState) {
3942         TRACE("Recording... not performing anything\n");
3943         return WINED3D_OK;
3944     }
3945
3946     /* Checked after the assignments to allow proper stateblock recording */
3947     if(oldValue == Value) {
3948         TRACE("App is setting the old value over, nothing to do\n");
3949         return WINED3D_OK;
3950     }
3951
3952     if(Stage > This->stateBlock->lowest_disabled_stage &&
3953        StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
3954         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
3955          * Changes in other states are important on disabled stages too
3956          */
3957         return WINED3D_OK;
3958     }
3959
3960     if(Type == WINED3DTSS_COLOROP) {
3961         int i;
3962
3963         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
3964             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
3965              * they have to be disabled
3966              *
3967              * The current stage is dirtified below.
3968              */
3969             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
3970                 TRACE("Additionally dirtifying stage %d\n", i);
3971                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3972             }
3973             This->stateBlock->lowest_disabled_stage = Stage;
3974             TRACE("New lowest disabled: %d\n", Stage);
3975         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
3976             /* Previously disabled stage enabled. Stages above it may need enabling
3977              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
3978              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
3979              *
3980              * Again stage Stage doesn't need to be dirtified here, it is handled below.
3981              */
3982
3983             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
3984                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
3985                     break;
3986                 }
3987                 TRACE("Additionally dirtifying stage %d due to enable\n", i);
3988                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3989             }
3990             This->stateBlock->lowest_disabled_stage = i;
3991             TRACE("New lowest disabled: %d\n", i);
3992         }
3993         if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3994             /* TODO: Built a stage -> texture unit mapping for register combiners */
3995         }
3996     }
3997
3998     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
3999
4000     /* Rebuild the stage -> gl texture unit mapping if register combiners are supported
4001      * If there is a pixel shader there will be a 1:1 mapping, no need to touch it. SetPixelShader
4002      * will call FindTexUnitMap too.
4003      */
4004     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4005         IWineD3DDeviceImpl_FindTexUnitMap(This);
4006     }
4007     return WINED3D_OK;
4008 }
4009
4010 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4011     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4012     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4013     *pValue = This->updateStateBlock->textureState[Stage][Type];
4014     return WINED3D_OK;
4015 }
4016
4017 /*****
4018  * Get / Set Texture
4019  *****/
4020 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4021
4022     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4023     IWineD3DBaseTexture   *oldTexture;
4024
4025     oldTexture = This->updateStateBlock->textures[Stage];
4026     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
4027
4028 #if 0 /* TODO: check so vertex textures */
4029     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4030         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4031         return WINED3D_OK;
4032     }
4033 #endif
4034
4035     if(pTexture != NULL) {
4036         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
4037          */
4038         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
4039             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4040             return WINED3DERR_INVALIDCALL;
4041         }
4042         This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
4043     }
4044
4045     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
4046     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4047
4048     This->updateStateBlock->set.textures[Stage]     = TRUE;
4049     This->updateStateBlock->changed.textures[Stage] = TRUE;
4050     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4051     This->updateStateBlock->textures[Stage]         = pTexture;
4052
4053     /* Handle recording of state blocks */
4054     if (This->isRecordingState) {
4055         TRACE("Recording... not performing anything\n");
4056         return WINED3D_OK;
4057     }
4058
4059     if(oldTexture == pTexture) {
4060         TRACE("App is setting the same texture again, nothing to do\n");
4061         return WINED3D_OK;
4062     }
4063
4064     /** NOTE: MSDN says that setTexture increases the reference count,
4065     * and the the application must set the texture back to null (or have a leaky application),
4066     * This means we should pass the refcount up to the parent
4067      *******************************/
4068     if (NULL != This->updateStateBlock->textures[Stage]) {
4069         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
4070         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
4071
4072         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4073         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
4074             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4075              * so the COLOROP and ALPHAOP have to be dirtified.
4076              */
4077             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4078             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4079         }
4080         if(bindCount == 1) {
4081             new->baseTexture.sampler = Stage;
4082         }
4083         /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
4084
4085     }
4086
4087     if (NULL != oldTexture) {
4088         IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
4089         LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
4090
4091         IWineD3DBaseTexture_Release(oldTexture);
4092         if(pTexture == NULL && Stage < MAX_TEXTURES) {
4093             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4094             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4095         }
4096
4097         if(bindCount && old->baseTexture.sampler == Stage) {
4098             int i;
4099             /* Have to do a search for the other sampler(s) where the texture is bound to
4100              * Shouldn't happen as long as apps bind a texture only to one stage
4101              */
4102             TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
4103             for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
4104                 if(This->updateStateBlock->textures[i] == oldTexture) {
4105                     old->baseTexture.sampler = i;
4106                     break;
4107                 }
4108             }
4109         }
4110     }
4111
4112     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
4113
4114     /* Verify the texture unit mapping(and rebuild it if needed) if we use nvrcs and no
4115      * pixel shader is used
4116      */
4117     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4118         IWineD3DDeviceImpl_FindTexUnitMap(This);
4119     }
4120
4121     return WINED3D_OK;
4122 }
4123
4124 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4125     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4126     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4127
4128     *ppTexture=This->stateBlock->textures[Stage];
4129     if (*ppTexture)
4130         IWineD3DBaseTexture_AddRef(*ppTexture);
4131
4132     return WINED3D_OK;
4133 }
4134
4135 /*****
4136  * Get Back Buffer
4137  *****/
4138 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4139                                                 IWineD3DSurface **ppBackBuffer) {
4140     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4141     IWineD3DSwapChain *swapChain;
4142     HRESULT hr;
4143
4144     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4145
4146     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4147     if (hr == WINED3D_OK) {
4148         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4149             IWineD3DSwapChain_Release(swapChain);
4150     } else {
4151         *ppBackBuffer = NULL;
4152     }
4153     return hr;
4154 }
4155
4156 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4157     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4158     WARN("(%p) : stub, calling idirect3d for now\n", This);
4159     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4160 }
4161
4162 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4163     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4164     IWineD3DSwapChain *swapChain;
4165     HRESULT hr;
4166
4167     if(iSwapChain > 0) {
4168         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4169         if (hr == WINED3D_OK) {
4170             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4171             IWineD3DSwapChain_Release(swapChain);
4172         } else {
4173             FIXME("(%p) Error getting display mode\n", This);
4174         }
4175     } else {
4176         /* Don't read the real display mode,
4177            but return the stored mode instead. X11 can't change the color
4178            depth, and some apps are pretty angry if they SetDisplayMode from
4179            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4180
4181            Also don't relay to the swapchain because with ddraw it's possible
4182            that there isn't a swapchain at all */
4183         pMode->Width = This->ddraw_width;
4184         pMode->Height = This->ddraw_height;
4185         pMode->Format = This->ddraw_format;
4186         pMode->RefreshRate = 0;
4187         hr = WINED3D_OK;
4188     }
4189
4190     return hr;
4191 }
4192
4193 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4194     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4195     TRACE("(%p)->(%p)\n", This, hWnd);
4196
4197     if(This->ddraw_fullscreen) {
4198         if(This->ddraw_window && This->ddraw_window != hWnd) {
4199             IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
4200         }
4201         if(hWnd && This->ddraw_window != hWnd) {
4202             IWineD3DDeviceImpl_SetupFullscreenWindow(iface, hWnd);
4203         }
4204     }
4205
4206     This->ddraw_window = hWnd;
4207     return WINED3D_OK;
4208 }
4209
4210 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4211     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4212     TRACE("(%p)->(%p)\n", This, hWnd);
4213
4214     *hWnd = This->ddraw_window;
4215     return WINED3D_OK;
4216 }
4217
4218 /*****
4219  * Stateblock related functions
4220  *****/
4221
4222 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4223     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4224     IWineD3DStateBlockImpl *object;
4225     HRESULT temp_result;
4226     int i;
4227
4228     TRACE("(%p)\n", This);
4229     
4230     if (This->isRecordingState) {
4231         return WINED3DERR_INVALIDCALL;
4232     }
4233     
4234     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4235     if (NULL == object ) {
4236         FIXME("(%p)Error allocating memory for stateblock\n", This);
4237         return E_OUTOFMEMORY;
4238     }
4239     TRACE("(%p) created object %p\n", This, object);
4240     object->wineD3DDevice= This;
4241     /** FIXME: object->parent       = parent; **/
4242     object->parent       = NULL;
4243     object->blockType    = WINED3DSBT_ALL;
4244     object->ref          = 1;
4245     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4246
4247     for(i = 0; i < LIGHTMAP_SIZE; i++) {
4248         list_init(&object->lightMap[i]);
4249     }
4250
4251     temp_result = allocate_shader_constants(object);
4252     if (WINED3D_OK != temp_result)
4253         return temp_result;
4254
4255     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4256     This->updateStateBlock = object;
4257     This->isRecordingState = TRUE;
4258
4259     TRACE("(%p) recording stateblock %p\n",This , object);
4260     return WINED3D_OK;
4261 }
4262
4263 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4264     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4265
4266     if (!This->isRecordingState) {
4267         FIXME("(%p) not recording! returning error\n", This);
4268         *ppStateBlock = NULL;
4269         return WINED3DERR_INVALIDCALL;
4270     }
4271
4272     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4273     This->isRecordingState = FALSE;
4274     This->updateStateBlock = This->stateBlock;
4275     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4276     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4277     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4278     return WINED3D_OK;
4279 }
4280
4281 /*****
4282  * Scene related functions
4283  *****/
4284 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4285     /* At the moment we have no need for any functionality at the beginning
4286        of a scene                                                          */
4287     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4288     TRACE("(%p)\n", This);
4289
4290     if(This->inScene) {
4291         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4292         return WINED3DERR_INVALIDCALL;
4293     }
4294     This->inScene = TRUE;
4295     return WINED3D_OK;
4296 }
4297
4298 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4299     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4300     TRACE("(%p)\n", This);
4301
4302     if(!This->inScene) {
4303         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4304         return WINED3DERR_INVALIDCALL;
4305     }
4306
4307     ENTER_GL();
4308     if(This->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) {
4309         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4310     }
4311     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4312     glFlush();
4313     checkGLcall("glFlush");
4314     LEAVE_GL();
4315
4316     This->inScene = FALSE;
4317     return WINED3D_OK;
4318 }
4319
4320 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4321                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4322                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4323     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4324     IWineD3DSwapChain *swapChain = NULL;
4325     int i;
4326     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4327
4328     TRACE("(%p) Presenting the frame\n", This);
4329
4330     for(i = 0 ; i < swapchains ; i ++) {
4331
4332         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4333         TRACE("presentinng chain %d, %p\n", i, swapChain);
4334         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4335         IWineD3DSwapChain_Release(swapChain);
4336     }
4337
4338     return WINED3D_OK;
4339 }
4340
4341 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4342                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4343     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4344     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0];
4345
4346     GLbitfield     glMask = 0;
4347     unsigned int   i;
4348     CONST WINED3DRECT* curRect;
4349
4350     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This,
4351           Count, pRects, Flags, Color, Z, Stencil);
4352
4353     if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
4354         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4355         /* TODO: What about depth stencil buffers without stencil bits? */
4356         return WINED3DERR_INVALIDCALL;
4357     }
4358
4359     ENTER_GL();
4360     /* This is for offscreen rendering as well as for multithreading, thus activate the set render target
4361      * and not the last active one.
4362      */
4363
4364     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4365         apply_fbo_state(iface);
4366     }
4367
4368     ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
4369
4370     glEnable(GL_SCISSOR_TEST);
4371     checkGLcall("glEnable GL_SCISSOR_TEST");
4372     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
4373     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
4374
4375     if (Count > 0 && pRects) {
4376         curRect = pRects;
4377     } else {
4378         curRect = NULL;
4379     }
4380
4381     /* Only set the values up once, as they are not changing */
4382     if (Flags & WINED3DCLEAR_STENCIL) {
4383         glClearStencil(Stencil);
4384         checkGLcall("glClearStencil");
4385         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4386         glStencilMask(0xFFFFFFFF);
4387     }
4388
4389     if (Flags & WINED3DCLEAR_ZBUFFER) {
4390         glDepthMask(GL_TRUE);
4391         glClearDepth(Z);
4392         checkGLcall("glClearDepth");
4393         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4394         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4395     }
4396
4397     if (Flags & WINED3DCLEAR_TARGET) {
4398         TRACE("Clearing screen with glClear to color %x\n", Color);
4399         glClearColor(D3DCOLOR_R(Color),
4400                      D3DCOLOR_G(Color),
4401                      D3DCOLOR_B(Color),
4402                      D3DCOLOR_A(Color));
4403         checkGLcall("glClearColor");
4404
4405         /* Clear ALL colors! */
4406         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4407         glMask = glMask | GL_COLOR_BUFFER_BIT;
4408     }
4409
4410     if (!curRect) {
4411         /* In drawable flag is set below */
4412
4413         glScissor(This->stateBlock->viewport.X,
4414                   (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4415                   (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4416                    This->stateBlock->viewport.Width,
4417                    This->stateBlock->viewport.Height);
4418         checkGLcall("glScissor");
4419         glClear(glMask);
4420         checkGLcall("glClear");
4421     } else {
4422         if(!(target->Flags & SFLAG_INDRAWABLE) &&
4423            !(wined3d_settings.offscreen_rendering_mode == ORM_FBO && This->render_offscreen && target->Flags & SFLAG_INTEXTURE)) {
4424
4425             if(curRect[0].x1 > 0 || curRect[0].y1 > 0 ||
4426                curRect[0].x2 < target->currentDesc.Width ||
4427                curRect[0].y2 < target->currentDesc.Height) {
4428                 TRACE("Partial clear, and surface not in drawable. Blitting texture to drawable\n");
4429                 blt_to_drawable(This, target);
4430             }
4431         }
4432
4433         /* Now process each rect in turn */
4434         for (i = 0; i < Count; i++) {
4435             /* Note gl uses lower left, width/height */
4436             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4437                   curRect[i].x1, curRect[i].y1, curRect[i].x2, curRect[i].y2,
4438                   curRect[i].x1, (target->currentDesc.Height - curRect[i].y2),
4439                   curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4440
4441             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4442              * The rectangle is not cleared, no error is returned, but further rectanlges are
4443              * still cleared if they are valid
4444              */
4445             if(curRect[i].x1 > curRect[i].x2 || curRect[i].y1 > curRect[i].y2) {
4446                 TRACE("Rectangle with negative dimensions, ignoring\n");
4447                 continue;
4448             }
4449
4450             if(This->render_offscreen) {
4451                 glScissor(curRect[i].x1, curRect[i].y1,
4452                           curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4453             } else {
4454                 glScissor(curRect[i].x1, target->currentDesc.Height - curRect[i].y2,
4455                           curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4456             }
4457             checkGLcall("glScissor");
4458
4459             glClear(glMask);
4460             checkGLcall("glClear");
4461         }
4462     }
4463
4464     /* Restore the old values (why..?) */
4465     if (Flags & WINED3DCLEAR_STENCIL) {
4466         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4467     }
4468     if (Flags & WINED3DCLEAR_TARGET) {
4469         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
4470         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4471                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4472                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4473                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4474     }
4475
4476     LEAVE_GL();
4477
4478     /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
4479      * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
4480      */
4481     if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4482         target->Flags |= SFLAG_INTEXTURE;
4483         target->Flags &= ~SFLAG_INSYSMEM;
4484     } else {
4485         target->Flags |= SFLAG_INDRAWABLE;
4486         target->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INSYSMEM);
4487     }
4488     return WINED3D_OK;
4489 }
4490
4491 /*****
4492  * Drawing functions
4493  *****/
4494 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4495                                                 UINT PrimitiveCount) {
4496
4497     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4498
4499     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4500                                debug_d3dprimitivetype(PrimitiveType),
4501                                StartVertex, PrimitiveCount);
4502
4503     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4504     if(This->stateBlock->streamIsUP) {
4505         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4506         This->stateBlock->streamIsUP = FALSE;
4507     }
4508
4509     if(This->stateBlock->loadBaseVertexIndex != 0) {
4510         This->stateBlock->loadBaseVertexIndex = 0;
4511         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4512     }
4513     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4514     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4515                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4516     return WINED3D_OK;
4517 }
4518
4519 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4520 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4521                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4522                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4523
4524     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4525     UINT                 idxStride = 2;
4526     IWineD3DIndexBuffer *pIB;
4527     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4528     GLuint vbo;
4529
4530     pIB = This->stateBlock->pIndexData;
4531     if (!pIB) {
4532         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4533          * without an index buffer set. (The first time at least...)
4534          * D3D8 simply dies, but I doubt it can do much harm to return
4535          * D3DERR_INVALIDCALL there as well. */
4536         ERR("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
4537         return WINED3DERR_INVALIDCALL;
4538     }
4539
4540     if(This->stateBlock->streamIsUP) {
4541         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4542         This->stateBlock->streamIsUP = FALSE;
4543     }
4544     vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
4545
4546     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4547           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4548           minIndex, NumVertices, startIndex, primCount);
4549
4550     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4551     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4552         idxStride = 2;
4553     } else {
4554         idxStride = 4;
4555     }
4556
4557     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4558         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4559         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4560     }
4561
4562     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4563                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4564
4565     return WINED3D_OK;
4566 }
4567
4568 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4569                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4570                                                     UINT VertexStreamZeroStride) {
4571     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4572
4573     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4574              debug_d3dprimitivetype(PrimitiveType),
4575              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4576
4577     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4578     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4579     This->stateBlock->streamOffset[0] = 0;
4580     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4581     This->stateBlock->streamIsUP = TRUE;
4582     This->stateBlock->loadBaseVertexIndex = 0;
4583
4584     /* TODO: Only mark dirty if drawing from a different UP address */
4585     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4586
4587     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4588                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4589
4590     /* MSDN specifies stream zero settings must be set to NULL */
4591     This->stateBlock->streamStride[0] = 0;
4592     This->stateBlock->streamSource[0] = NULL;
4593
4594     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4595      * the new stream sources or use UP drawing again
4596      */
4597     return WINED3D_OK;
4598 }
4599
4600 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4601                                                              UINT MinVertexIndex, UINT NumVertices,
4602                                                              UINT PrimitiveCount, CONST void* pIndexData,
4603                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4604                                                              UINT VertexStreamZeroStride) {
4605     int                 idxStride;
4606     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4607
4608     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4609              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4610              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4611              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4612
4613     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4614         idxStride = 2;
4615     } else {
4616         idxStride = 4;
4617     }
4618
4619     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4620     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4621     This->stateBlock->streamIsUP = TRUE;
4622     This->stateBlock->streamOffset[0] = 0;
4623     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4624
4625     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4626     This->stateBlock->baseVertexIndex = 0;
4627     This->stateBlock->loadBaseVertexIndex = 0;
4628     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4629     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4630     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4631
4632     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4633
4634     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4635     This->stateBlock->streamSource[0] = NULL;
4636     This->stateBlock->streamStride[0] = 0;
4637     This->stateBlock->pIndexData = NULL;
4638     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4639      * SetStreamSource to specify a vertex buffer
4640      */
4641
4642     return WINED3D_OK;
4643 }
4644
4645 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4646     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4647
4648     /* Mark the state dirty until we have nicer tracking
4649      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4650      * that value.
4651      */
4652     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4653     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4654     This->stateBlock->baseVertexIndex = 0;
4655     This->up_strided = DrawPrimStrideData;
4656     This->stateBlock->streamIsUP = TRUE;
4657     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4658     This->up_strided = NULL;
4659     return WINED3D_OK;
4660 }
4661  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4662 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4663     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4664     HRESULT hr = WINED3D_OK;
4665     WINED3DRESOURCETYPE sourceType;
4666     WINED3DRESOURCETYPE destinationType;
4667     int i ,levels;
4668
4669     /* TODO: think about moving the code into IWineD3DBaseTexture  */
4670
4671     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4672
4673     /* verify that the source and destination textures aren't NULL */
4674     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4675         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4676              This, pSourceTexture, pDestinationTexture);
4677         hr = WINED3DERR_INVALIDCALL;
4678     }
4679
4680     if (pSourceTexture == pDestinationTexture) {
4681         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4682              This, pSourceTexture, pDestinationTexture);
4683         hr = WINED3DERR_INVALIDCALL;
4684     }
4685     /* Verify that the source and destination textures are the same type */
4686     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
4687     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4688
4689     if (sourceType != destinationType) {
4690         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4691              This);
4692         hr = WINED3DERR_INVALIDCALL;
4693     }
4694
4695     /* check that both textures have the identical numbers of levels  */
4696     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4697         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4698         hr = WINED3DERR_INVALIDCALL;
4699     }
4700
4701     if (WINED3D_OK == hr) {
4702
4703         /* Make sure that the destination texture is loaded */
4704         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4705
4706         /* Update every surface level of the texture */
4707         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4708
4709         switch (sourceType) {
4710         case WINED3DRTYPE_TEXTURE:
4711             {
4712                 IWineD3DSurface *srcSurface;
4713                 IWineD3DSurface *destSurface;
4714
4715                 for (i = 0 ; i < levels ; ++i) {
4716                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
4717                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4718                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4719                     IWineD3DSurface_Release(srcSurface);
4720                     IWineD3DSurface_Release(destSurface);
4721                     if (WINED3D_OK != hr) {
4722                         WARN("(%p) : Call to update surface failed\n", This);
4723                         return hr;
4724                     }
4725                 }
4726             }
4727             break;
4728         case WINED3DRTYPE_CUBETEXTURE:
4729             {
4730                 IWineD3DSurface *srcSurface;
4731                 IWineD3DSurface *destSurface;
4732                 WINED3DCUBEMAP_FACES faceType;
4733
4734                 for (i = 0 ; i < levels ; ++i) {
4735                     /* Update each cube face */
4736                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4737                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
4738                         if (WINED3D_OK != hr) {
4739                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4740                         } else {
4741                             TRACE("Got srcSurface %p\n", srcSurface);
4742                         }
4743                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4744                         if (WINED3D_OK != hr) {
4745                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4746                         } else {
4747                             TRACE("Got desrSurface %p\n", destSurface);
4748                         }
4749                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4750                         IWineD3DSurface_Release(srcSurface);
4751                         IWineD3DSurface_Release(destSurface);
4752                         if (WINED3D_OK != hr) {
4753                             WARN("(%p) : Call to update surface failed\n", This);
4754                             return hr;
4755                         }
4756                     }
4757                 }
4758             }
4759             break;
4760 #if 0 /* TODO: Add support for volume textures */
4761         case WINED3DRTYPE_VOLUMETEXTURE:
4762             {
4763                 IWineD3DVolume  srcVolume  = NULL;
4764                 IWineD3DSurface destVolume = NULL;
4765
4766                 for (i = 0 ; i < levels ; ++i) {
4767                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
4768                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4769                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4770                     IWineD3DVolume_Release(srcSurface);
4771                     IWineD3DVolume_Release(destSurface);
4772                     if (WINED3D_OK != hr) {
4773                         WARN("(%p) : Call to update volume failed\n", This);
4774                         return hr;
4775                     }
4776                 }
4777             }
4778             break;
4779 #endif
4780         default:
4781             FIXME("(%p) : Unsupported source and destination type\n", This);
4782             hr = WINED3DERR_INVALIDCALL;
4783         }
4784     }
4785
4786     return hr;
4787 }
4788
4789 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4790     IWineD3DSwapChain *swapChain;
4791     HRESULT hr;
4792     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4793     if(hr == WINED3D_OK) {
4794         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4795                 IWineD3DSwapChain_Release(swapChain);
4796     }
4797     return hr;
4798 }
4799
4800 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4801     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4802     /* return a sensible default */
4803     *pNumPasses = 1;
4804     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
4805     FIXME("(%p) : stub\n", This);
4806     return WINED3D_OK;
4807 }
4808
4809 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4810     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4811     int j;
4812     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4813     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4814         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4815         return WINED3DERR_INVALIDCALL;
4816     }
4817     for (j = 0; j < 256; ++j) {
4818         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
4819         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4820         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
4821         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4822     }
4823     TRACE("(%p) : returning\n", This);
4824     return WINED3D_OK;
4825 }
4826
4827 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4828     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4829     int j;
4830     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4831     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4832         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4833         return WINED3DERR_INVALIDCALL;
4834     }
4835     for (j = 0; j < 256; ++j) {
4836         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
4837         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4838         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
4839         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4840     }
4841     TRACE("(%p) : returning\n", This);
4842     return WINED3D_OK;
4843 }
4844
4845 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4846     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4847     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4848     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4849         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4850         return WINED3DERR_INVALIDCALL;
4851     }
4852     /*TODO: stateblocks */
4853     This->currentPalette = PaletteNumber;
4854     TRACE("(%p) : returning\n", This);
4855     return WINED3D_OK;
4856 }
4857
4858 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4859     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4860     if (PaletteNumber == NULL) {
4861         WARN("(%p) : returning Invalid Call\n", This);
4862         return WINED3DERR_INVALIDCALL;
4863     }
4864     /*TODO: stateblocks */
4865     *PaletteNumber = This->currentPalette;
4866     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
4867     return WINED3D_OK;
4868 }
4869
4870 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4871     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4872     static BOOL showFixmes = TRUE;
4873     if (showFixmes) {
4874         FIXME("(%p) : stub\n", This);
4875         showFixmes = FALSE;
4876     }
4877
4878     This->softwareVertexProcessing = bSoftware;
4879     return WINED3D_OK;
4880 }
4881
4882
4883 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4884     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4885     static BOOL showFixmes = TRUE;
4886     if (showFixmes) {
4887         FIXME("(%p) : stub\n", This);
4888         showFixmes = FALSE;
4889     }
4890     return This->softwareVertexProcessing;
4891 }
4892
4893
4894 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
4895     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4896     IWineD3DSwapChain *swapChain;
4897     HRESULT hr;
4898
4899     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4900
4901     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4902     if(hr == WINED3D_OK){
4903         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4904         IWineD3DSwapChain_Release(swapChain);
4905     }else{
4906         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
4907     }
4908     return hr;
4909 }
4910
4911
4912 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4913     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4914     static BOOL showfixmes = TRUE;
4915     if(nSegments != 0.0f) {
4916         if( showfixmes) {
4917             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4918             showfixmes = FALSE;
4919         }
4920     }
4921     return WINED3D_OK;
4922 }
4923
4924 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4925     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4926     static BOOL showfixmes = TRUE;
4927     if( showfixmes) {
4928         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4929         showfixmes = FALSE;
4930     }
4931     return 0.0f;
4932 }
4933
4934 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4935     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
4936     /** TODO: remove casts to IWineD3DSurfaceImpl
4937      *       NOTE: move code to surface to accomplish this
4938       ****************************************/
4939     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
4940     int srcWidth, srcHeight;
4941     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4942     WINED3DFORMAT destFormat, srcFormat;
4943     UINT          destSize;
4944     int srcLeft, destLeft, destTop;
4945     WINED3DPOOL       srcPool, destPool;
4946     int offset    = 0;
4947     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4948     glDescriptor *glDescription = NULL;
4949
4950     WINED3DSURFACE_DESC  winedesc;
4951
4952     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
4953     memset(&winedesc, 0, sizeof(winedesc));
4954     winedesc.Width  = &srcSurfaceWidth;
4955     winedesc.Height = &srcSurfaceHeight;
4956     winedesc.Pool   = &srcPool;
4957     winedesc.Format = &srcFormat;
4958
4959     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4960
4961     winedesc.Width  = &destSurfaceWidth;
4962     winedesc.Height = &destSurfaceHeight;
4963     winedesc.Pool   = &destPool;
4964     winedesc.Format = &destFormat;
4965     winedesc.Size   = &destSize;
4966
4967     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4968
4969     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
4970         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
4971         return WINED3DERR_INVALIDCALL;
4972     }
4973
4974     if (destFormat == WINED3DFMT_UNKNOWN) {
4975         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
4976         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
4977
4978         /* Get the update surface description */
4979         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4980     }
4981
4982     ENTER_GL();
4983
4984     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4985
4986     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4987         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
4988         checkGLcall("glActiveTextureARB");
4989     }
4990
4991     /* Make sure the surface is loaded and up to date */
4992     IWineD3DSurface_PreLoad(pDestinationSurface);
4993
4994     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4995
4996     /* this needs to be done in lines if the sourceRect != the sourceWidth */
4997     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
4998     srcHeight  = pSourceRect ? pSourceRect->bottom - pSourceRect->top   : srcSurfaceHeight;
4999     srcLeft    = pSourceRect ? pSourceRect->left : 0;
5000     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5001     destTop    = pDestPoint  ? pDestPoint->y : 0;
5002
5003
5004     /* This function doesn't support compressed textures
5005     the pitch is just bytesPerPixel * width */
5006     if(srcWidth != srcSurfaceWidth  || srcLeft ){
5007         rowoffset = srcSurfaceWidth * pSrcSurface->bytesPerPixel;
5008         offset   += srcLeft * pSrcSurface->bytesPerPixel;
5009         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5010     }
5011     /* TODO DXT formats */
5012
5013     if(pSourceRect != NULL && pSourceRect->top != 0){
5014        offset +=  pSourceRect->top * srcSurfaceWidth * pSrcSurface->bytesPerPixel;
5015     }
5016     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5017     ,This
5018     ,glDescription->level
5019     ,destLeft
5020     ,destTop
5021     ,srcWidth
5022     ,srcHeight
5023     ,glDescription->glFormat
5024     ,glDescription->glType
5025     ,IWineD3DSurface_GetData(pSourceSurface)
5026     );
5027
5028     /* Sanity check */
5029     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5030
5031         /* need to lock the surface to get the data */
5032         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5033     }
5034
5035     /* TODO: Cube and volume support */
5036     if(rowoffset != 0){
5037         /* not a whole row so we have to do it a line at a time */
5038         int j;
5039
5040         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5041         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5042
5043         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5044
5045                 glTexSubImage2D(glDescription->target
5046                     ,glDescription->level
5047                     ,destLeft
5048                     ,j
5049                     ,srcWidth
5050                     ,1
5051                     ,glDescription->glFormat
5052                     ,glDescription->glType
5053                     ,data /* could be quicker using */
5054                 );
5055             data += rowoffset;
5056         }
5057
5058     } else { /* Full width, so just write out the whole texture */
5059
5060         if (WINED3DFMT_DXT1 == destFormat ||
5061             WINED3DFMT_DXT2 == destFormat ||
5062             WINED3DFMT_DXT3 == destFormat ||
5063             WINED3DFMT_DXT4 == destFormat ||
5064             WINED3DFMT_DXT5 == destFormat) {
5065             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5066                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5067                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5068                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5069                 } if (destFormat != srcFormat) {
5070                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5071                 } else {
5072                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5073                                                         glDescription->level,
5074                                                         glDescription->glFormatInternal,
5075                                                         srcWidth,
5076                                                         srcHeight,
5077                                                         0,
5078                                                         destSize,
5079                                                         IWineD3DSurface_GetData(pSourceSurface));
5080                 }
5081             } else {
5082                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5083             }
5084
5085
5086         } else {
5087             glTexSubImage2D(glDescription->target
5088                     ,glDescription->level
5089                     ,destLeft
5090                     ,destTop
5091                     ,srcWidth
5092                     ,srcHeight
5093                     ,glDescription->glFormat
5094                     ,glDescription->glType
5095                     ,IWineD3DSurface_GetData(pSourceSurface)
5096                 );
5097         }
5098      }
5099     checkGLcall("glTexSubImage2D");
5100
5101     LEAVE_GL();
5102
5103     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags &= ~SFLAG_INSYSMEM;
5104     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_INTEXTURE;
5105     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
5106
5107     return WINED3D_OK;
5108 }
5109
5110 /* Implementation details at http://developer.nvidia.com/attach/6494
5111 and
5112 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5113 hmm.. no longer supported use
5114 OpenGL evaluators or  tessellate surfaces within your application.
5115 */
5116
5117 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5118 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5119     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5120     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5121     FIXME("(%p) : Stub\n", This);
5122     return WINED3D_OK;
5123
5124 }
5125
5126 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5127 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5128     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5129     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5130     FIXME("(%p) : Stub\n", This);
5131     return WINED3D_OK;
5132 }
5133
5134 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5135     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5136     TRACE("(%p) Handle(%d)\n", This, Handle);
5137     FIXME("(%p) : Stub\n", This);
5138     return WINED3D_OK;
5139 }
5140
5141 static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) {
5142     HRESULT hr;
5143     IWineD3DSwapChain *swapchain;
5144
5145     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain);
5146     if (SUCCEEDED(hr)) {
5147         IWineD3DSwapChain_Release((IUnknown *)swapchain);
5148         return swapchain;
5149     }
5150
5151     return NULL;
5152 }
5153
5154 static void bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) {
5155     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5156
5157     if (!*fbo) {
5158         GL_EXTCALL(glGenFramebuffersEXT(1, fbo));
5159         checkGLcall("glGenFramebuffersEXT()");
5160     }
5161     GL_EXTCALL(glBindFramebufferEXT(target, *fbo));
5162     checkGLcall("glBindFramebuffer()");
5163 }
5164
5165 static void attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) {
5166     const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface;
5167     IWineD3DBaseTextureImpl *texture_impl;
5168     GLenum texttarget, target;
5169     GLint old_binding;
5170
5171     texttarget = surface_impl->glDescription.target;
5172     target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5173     glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5174
5175     IWineD3DSurface_PreLoad(surface);
5176
5177     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5178     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5179     glBindTexture(target, old_binding);
5180
5181     /* Update base texture states array */
5182     if (SUCCEEDED(IWineD3DSurface_GetContainer(surface, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
5183         texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
5184         texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
5185         if (texture_impl->baseTexture.bindCount) {
5186             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
5187         }
5188
5189         IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
5190     }
5191
5192     GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, surface_impl->glDescription.textureName, 0));
5193
5194     checkGLcall("attach_surface_fbo");
5195 }
5196
5197 static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONST WINED3DRECT *rect, WINED3DCOLOR color) {
5198     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5199     IWineD3DSwapChain *swapchain;
5200
5201     swapchain = get_swapchain(surface);
5202     if (swapchain) {
5203         GLenum buffer;
5204
5205         TRACE("Surface %p is onscreen\n", surface);
5206
5207         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5208         buffer = surface_get_gl_buffer(surface, swapchain);
5209         glDrawBuffer(buffer);
5210         checkGLcall("glDrawBuffer()");
5211     } else {
5212         TRACE("Surface %p is offscreen\n", surface);
5213         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->dst_fbo);
5214         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface);
5215     }
5216
5217     if (rect) {
5218         glEnable(GL_SCISSOR_TEST);
5219         if(!swapchain) {
5220             glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1);
5221         } else {
5222             glScissor(rect->x1, ((IWineD3DSurfaceImpl *)surface)->currentDesc.Height - rect->y2,
5223                     rect->x2 - rect->x1, rect->y2 - rect->y1);
5224         }
5225         checkGLcall("glScissor");
5226     } else {
5227         glDisable(GL_SCISSOR_TEST);
5228     }
5229     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
5230
5231     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5232     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
5233
5234     glClearColor(D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color));
5235     glClear(GL_COLOR_BUFFER_BIT);
5236     checkGLcall("glClear");
5237
5238     if (This->render_offscreen) {
5239         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5240     } else {
5241         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5242         checkGLcall("glBindFramebuffer()");
5243     }
5244
5245     if (swapchain && surface == ((IWineD3DSwapChainImpl *)swapchain)->frontBuffer
5246             && ((IWineD3DSwapChainImpl *)swapchain)->backBuffer) {
5247         glDrawBuffer(GL_BACK);
5248         checkGLcall("glDrawBuffer()");
5249     }
5250 }
5251
5252 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
5253     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5254     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
5255     WINEDDBLTFX BltFx;
5256     TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This, pSurface, pRect, color);
5257
5258     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
5259         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5260         return WINED3DERR_INVALIDCALL;
5261     }
5262
5263     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5264         color_fill_fbo(iface, pSurface, pRect, color);
5265         return WINED3D_OK;
5266     } else {
5267         /* Just forward this to the DirectDraw blitting engine */
5268         memset(&BltFx, 0, sizeof(BltFx));
5269         BltFx.dwSize = sizeof(BltFx);
5270         BltFx.u5.dwFillColor = color;
5271         return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE);
5272     }
5273 }
5274
5275 /* rendertarget and deptth stencil functions */
5276 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5277     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5278
5279     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5280         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5281         return WINED3DERR_INVALIDCALL;
5282     }
5283
5284     *ppRenderTarget = This->render_targets[RenderTargetIndex];
5285     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5286     /* Note inc ref on returned surface */
5287     if(*ppRenderTarget != NULL)
5288         IWineD3DSurface_AddRef(*ppRenderTarget);
5289     return WINED3D_OK;
5290 }
5291
5292 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
5293     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5294     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
5295     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
5296     IWineD3DSwapChainImpl *Swapchain;
5297     HRESULT hr;
5298
5299     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
5300
5301     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
5302     if(hr != WINED3D_OK) {
5303         ERR("Can't get the swapchain\n");
5304         return hr;
5305     }
5306
5307     /* Make sure to release the swapchain */
5308     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
5309
5310     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
5311         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5312         return WINED3DERR_INVALIDCALL;
5313     }
5314     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
5315         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5316         return WINED3DERR_INVALIDCALL;
5317     }
5318
5319     if(Swapchain->frontBuffer != Front) {
5320         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
5321
5322         if(Swapchain->frontBuffer)
5323             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
5324         Swapchain->frontBuffer = Front;
5325
5326         if(Swapchain->frontBuffer) {
5327             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
5328         }
5329     }
5330
5331     if(Back && !Swapchain->backBuffer) {
5332         /* We need memory for the back buffer array - only one back buffer this way */
5333         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
5334         if(!Swapchain->backBuffer) {
5335             ERR("Out of memory\n");
5336             return E_OUTOFMEMORY;
5337         }
5338     }
5339
5340     if(Swapchain->backBuffer[0] != Back) {
5341         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
5342
5343         /* What to do about the context here in the case of multithreading? Not sure.
5344          * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
5345          */
5346         ENTER_GL();
5347         if(!Swapchain->backBuffer[0]) {
5348             /* GL was told to draw to the front buffer at creation,
5349              * undo that
5350              */
5351             glDrawBuffer(GL_BACK);
5352             checkGLcall("glDrawBuffer(GL_BACK)");
5353             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
5354             Swapchain->presentParms.BackBufferCount = 1;
5355         } else if (!Back) {
5356             /* That makes problems - disable for now */
5357             /* glDrawBuffer(GL_FRONT); */
5358             checkGLcall("glDrawBuffer(GL_FRONT)");
5359             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
5360             Swapchain->presentParms.BackBufferCount = 0;
5361         }
5362         LEAVE_GL();
5363
5364         if(Swapchain->backBuffer[0])
5365             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
5366         Swapchain->backBuffer[0] = Back;
5367
5368         if(Swapchain->backBuffer[0]) {
5369             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5370         } else {
5371             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5372         }
5373
5374     }
5375
5376     return WINED3D_OK;
5377 }
5378
5379 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5380     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5381     *ppZStencilSurface = This->depthStencilBuffer;
5382     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5383
5384     if(*ppZStencilSurface != NULL) {
5385         /* Note inc ref on returned surface */
5386         IWineD3DSurface_AddRef(*ppZStencilSurface);
5387     }
5388     return WINED3D_OK;
5389 }
5390
5391 /* TODO: Handle stencil attachments */
5392 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5393     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5394     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5395
5396     TRACE("Set depth stencil to %p\n", depth_stencil);
5397
5398     if (depth_stencil_impl) {
5399         if (depth_stencil_impl->current_renderbuffer) {
5400             GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id));
5401             checkGLcall("glFramebufferRenderbufferEXT()");
5402         } else {
5403             IWineD3DBaseTextureImpl *texture_impl;
5404             GLenum texttarget, target;
5405             GLint old_binding = 0;
5406
5407             texttarget = depth_stencil_impl->glDescription.target;
5408             target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5409             glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5410
5411             IWineD3DSurface_PreLoad(depth_stencil);
5412
5413             glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5414             glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5415             glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5416             glBindTexture(target, old_binding);
5417
5418             /* Update base texture states array */
5419             if (SUCCEEDED(IWineD3DSurface_GetContainer(depth_stencil, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
5420                 texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
5421                 texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
5422                 if (texture_impl->baseTexture.bindCount) {
5423                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
5424                 }
5425
5426                 IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
5427             }
5428
5429             GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5430             checkGLcall("glFramebufferTexture2DEXT()");
5431         }
5432     } else {
5433         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5434         checkGLcall("glFramebufferTexture2DEXT()");
5435     }
5436 }
5437
5438 static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5439     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5440     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5441
5442     TRACE("Set render target %u to %p\n", idx, render_target);
5443
5444     if (rtimpl) {
5445         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, idx, render_target);
5446         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5447     } else {
5448         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5449         checkGLcall("glFramebufferTexture2DEXT()");
5450
5451         This->draw_buffers[idx] = GL_NONE;
5452     }
5453 }
5454
5455 static void check_fbo_status(IWineD3DDevice *iface) {
5456     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5457     GLenum status;
5458
5459     status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
5460     if (status == GL_FRAMEBUFFER_COMPLETE_EXT) {
5461         TRACE("FBO complete\n");
5462     } else {
5463         FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status);
5464
5465         /* Dump the FBO attachments */
5466         if (status == GL_FRAMEBUFFER_UNSUPPORTED_EXT) {
5467             IWineD3DSurfaceImpl *attachment;
5468             int i;
5469
5470             for (i = 0; i < GL_LIMITS(buffers); ++i) {
5471                 attachment = (IWineD3DSurfaceImpl *)This->fbo_color_attachments[i];
5472                 if (attachment) {
5473                     FIXME("\tColor attachment %d: (%p) %s %ux%u\n", i, attachment, debug_d3dformat(attachment->resource.format),
5474                             attachment->pow2Width, attachment->pow2Height);
5475                 }
5476             }
5477             attachment = (IWineD3DSurfaceImpl *)This->fbo_depth_attachment;
5478             if (attachment) {
5479                 FIXME("\tDepth attachment: (%p) %s %ux%u\n", attachment, debug_d3dformat(attachment->resource.format),
5480                         attachment->pow2Width, attachment->pow2Height);
5481             }
5482         }
5483     }
5484 }
5485
5486 static BOOL depth_mismatch_fbo(IWineD3DDevice *iface) {
5487     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5488     IWineD3DSurfaceImpl *rt_impl = (IWineD3DSurfaceImpl *)This->render_targets[0];
5489     IWineD3DSurfaceImpl *ds_impl = (IWineD3DSurfaceImpl *)This->stencilBufferTarget;
5490
5491     if (!ds_impl) return FALSE;
5492
5493     if (ds_impl->current_renderbuffer) {
5494         return (rt_impl->pow2Width != ds_impl->current_renderbuffer->width ||
5495                 rt_impl->pow2Height != ds_impl->current_renderbuffer->height);
5496     }
5497
5498     return (rt_impl->pow2Width != ds_impl->pow2Width ||
5499             rt_impl->pow2Height != ds_impl->pow2Height);
5500 }
5501
5502 void apply_fbo_state(IWineD3DDevice *iface) {
5503     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5504     unsigned int i;
5505
5506     if (This->render_offscreen) {
5507         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5508
5509         /* Apply render targets */
5510         for (i = 0; i < GL_LIMITS(buffers); ++i) {
5511             IWineD3DSurface *render_target = This->render_targets[i];
5512             if (This->fbo_color_attachments[i] != render_target) {
5513                 set_render_target_fbo(iface, i, render_target);
5514                 This->fbo_color_attachments[i] = render_target;
5515             }
5516         }
5517
5518         /* Apply depth targets */
5519         if (This->fbo_depth_attachment != This->stencilBufferTarget || depth_mismatch_fbo(iface)) {
5520             unsigned int w = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Width;
5521             unsigned int h = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Height;
5522
5523             if (This->stencilBufferTarget) {
5524                 surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h);
5525             }
5526             set_depth_stencil_fbo(iface, This->stencilBufferTarget);
5527             This->fbo_depth_attachment = This->stencilBufferTarget;
5528         }
5529
5530         if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5531             GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5532             checkGLcall("glDrawBuffers()");
5533         } else {
5534             glDrawBuffer(This->draw_buffers[0]);
5535             checkGLcall("glDrawBuffer()");
5536         }
5537     } else {
5538         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5539     }
5540
5541     check_fbo_status(iface);
5542 }
5543
5544 void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect,
5545         IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) {
5546     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5547     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
5548     IWineD3DSwapChain *src_swapchain, *dst_swapchain;
5549     GLenum gl_filter;
5550
5551     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
5552             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
5553     TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2);
5554     TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2);
5555
5556     switch (filter) {
5557         case WINED3DTEXF_LINEAR:
5558             gl_filter = GL_LINEAR;
5559             break;
5560
5561         default:
5562             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
5563         case WINED3DTEXF_NONE:
5564         case WINED3DTEXF_POINT:
5565             gl_filter = GL_NEAREST;
5566             break;
5567     }
5568
5569     /* Attach src surface to src fbo */
5570     src_swapchain = get_swapchain(src_surface);
5571     ENTER_GL();
5572     if (src_swapchain) {
5573         GLenum buffer;
5574
5575         TRACE("Source surface %p is onscreen\n", src_surface);
5576         ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD);
5577
5578         GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0));
5579         buffer = surface_get_gl_buffer(src_surface, src_swapchain);
5580         glReadBuffer(buffer);
5581         checkGLcall("glReadBuffer()");
5582
5583         src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
5584         src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
5585     } else {
5586         TRACE("Source surface %p is offscreen\n", src_surface);
5587         bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo);
5588         attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
5589         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
5590         checkGLcall("glReadBuffer()");
5591     }
5592
5593     /* Attach dst surface to dst fbo */
5594     dst_swapchain = get_swapchain(dst_surface);
5595     if (dst_swapchain) {
5596         GLenum buffer;
5597
5598         TRACE("Destination surface %p is onscreen\n", dst_surface);
5599         ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD);
5600
5601         GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0));
5602         buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
5603         glDrawBuffer(buffer);
5604         checkGLcall("glDrawBuffer()");
5605
5606         dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
5607         dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
5608     } else {
5609         TRACE("Destination surface %p is offscreen\n", dst_surface);
5610
5611         /* No src or dst swapchain? Make sure some context is active(multithreading) */
5612         if(!src_swapchain) {
5613             ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5614         }
5615
5616         bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo);
5617         attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
5618         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
5619         checkGLcall("glDrawBuffer()");
5620     }
5621     glDisable(GL_SCISSOR_TEST);
5622     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
5623
5624     if (flip) {
5625         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
5626                 dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter));
5627         checkGLcall("glBlitFramebuffer()");
5628     } else {
5629         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
5630                 dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter));
5631         checkGLcall("glBlitFramebuffer()");
5632     }
5633
5634     if (This->render_offscreen) {
5635         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5636     } else {
5637         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5638         checkGLcall("glBindFramebuffer()");
5639     }
5640
5641     /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
5642     if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer
5643             && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) {
5644         glDrawBuffer(GL_BACK);
5645         checkGLcall("glDrawBuffer()");
5646     }
5647     LEAVE_GL();
5648 }
5649
5650 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5651     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5652     WINED3DVIEWPORT viewport;
5653
5654     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5655
5656     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5657         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5658         return WINED3DERR_INVALIDCALL;
5659     }
5660
5661     /* MSDN says that null disables the render target
5662     but a device must always be associated with a render target
5663     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5664
5665     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5666     for more details
5667     */
5668     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5669         FIXME("Trying to set render target 0 to NULL\n");
5670         return WINED3DERR_INVALIDCALL;
5671     }
5672     if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5673         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);
5674         return WINED3DERR_INVALIDCALL;
5675     }
5676
5677     /* If we are trying to set what we already have, don't bother */
5678     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5679         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5680         return WINED3D_OK;
5681     }
5682     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5683     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5684     This->render_targets[RenderTargetIndex] = pRenderTarget;
5685
5686     /* Render target 0 is special */
5687     if(RenderTargetIndex == 0) {
5688         /* Finally, reset the viewport as the MSDN states. */
5689         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5690         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5691         viewport.X      = 0;
5692         viewport.Y      = 0;
5693         viewport.MaxZ   = 1.0f;
5694         viewport.MinZ   = 0.0f;
5695         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5696         /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
5697          * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
5698          */
5699         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
5700
5701         /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
5702          * ctx properly.
5703          * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
5704          * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
5705          */
5706         ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
5707     }
5708     return WINED3D_OK;
5709 }
5710
5711 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5712     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5713     HRESULT  hr = WINED3D_OK;
5714     IWineD3DSurface *tmp;
5715
5716     TRACE("(%p) Swapping z-buffer\n",This);
5717
5718     if (pNewZStencil == This->stencilBufferTarget) {
5719         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5720     } else {
5721         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5722         * depending on the renter target implementation being used.
5723         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5724         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5725         * stencil buffer and incure an extra memory overhead
5726          ******************************************************/
5727
5728         tmp = This->stencilBufferTarget;
5729         This->stencilBufferTarget = pNewZStencil;
5730         This->depth_copy_state = WINED3D_DCS_NO_COPY;
5731         /* should we be calling the parent or the wined3d surface? */
5732         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5733         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5734         hr = WINED3D_OK;
5735
5736         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
5737             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5738             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
5739             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
5740             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
5741         }
5742     }
5743
5744     return hr;
5745 }
5746
5747 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5748                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5749     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5750     /* TODO: the use of Impl is deprecated. */
5751     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5752     WINED3DLOCKED_RECT lockedRect;
5753
5754     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5755
5756     /* some basic validation checks */
5757     if(This->cursorTexture) {
5758         ENTER_GL();
5759         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5760         glDeleteTextures(1, &This->cursorTexture);
5761         LEAVE_GL();
5762         This->cursorTexture = 0;
5763     }
5764
5765     if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
5766         This->haveHardwareCursor = TRUE;
5767     else
5768         This->haveHardwareCursor = FALSE;
5769
5770     if(pCursorBitmap) {
5771         WINED3DLOCKED_RECT rect;
5772
5773         /* MSDN: Cursor must be A8R8G8B8 */
5774         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5775             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5776             return WINED3DERR_INVALIDCALL;
5777         }
5778
5779         /* MSDN: Cursor must be smaller than the display mode */
5780         if(pSur->currentDesc.Width > This->ddraw_width ||
5781            pSur->currentDesc.Height > This->ddraw_height) {
5782             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);
5783             return WINED3DERR_INVALIDCALL;
5784         }
5785
5786         if (!This->haveHardwareCursor) {
5787             /* TODO: MSDN: Cursor sizes must be a power of 2 */
5788
5789             /* Do not store the surface's pointer because the application may
5790              * release it after setting the cursor image. Windows doesn't
5791              * addref the set surface, so we can't do this either without
5792              * creating circular refcount dependencies. Copy out the gl texture
5793              * instead.
5794              */
5795             This->cursorWidth = pSur->currentDesc.Width;
5796             This->cursorHeight = pSur->currentDesc.Height;
5797             if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
5798             {
5799                 const PixelFormatDesc *tableEntry = getFormatDescEntry(WINED3DFMT_A8R8G8B8);
5800                 char *mem, *bits = (char *)rect.pBits;
5801                 GLint intfmt = tableEntry->glInternal;
5802                 GLint format = tableEntry->glFormat;
5803                 GLint type = tableEntry->glType;
5804                 INT height = This->cursorHeight;
5805                 INT width = This->cursorWidth;
5806                 INT bpp = tableEntry->bpp;
5807                 INT i;
5808
5809                 /* Reformat the texture memory (pitch and width can be
5810                  * different) */
5811                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
5812                 for(i = 0; i < height; i++)
5813                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
5814                 IWineD3DSurface_UnlockRect(pCursorBitmap);
5815                 ENTER_GL();
5816
5817                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
5818                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
5819                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
5820                 }
5821
5822                 /* Make sure that a proper texture unit is selected */
5823                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
5824                     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5825                     checkGLcall("glActiveTextureARB");
5826                 }
5827                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
5828                 /* Create a new cursor texture */
5829                 glGenTextures(1, &This->cursorTexture);
5830                 checkGLcall("glGenTextures");
5831                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
5832                 checkGLcall("glBindTexture");
5833                 /* Copy the bitmap memory into the cursor texture */
5834                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
5835                 HeapFree(GetProcessHeap(), 0, mem);
5836                 checkGLcall("glTexImage2D");
5837
5838                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
5839                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
5840                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
5841                 }
5842
5843                 LEAVE_GL();
5844             }
5845             else
5846             {
5847                 FIXME("A cursor texture was not returned.\n");
5848                 This->cursorTexture = 0;
5849             }
5850         }
5851         else
5852         {
5853             /* Draw a hardware cursor */
5854             ICONINFO cursorInfo;
5855             HCURSOR cursor;
5856             /* Create and clear maskBits because it is not needed for
5857              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
5858              * chunks. */
5859             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5860                 (pSur->currentDesc.Width * pSur->currentDesc.Height / 8));
5861             IWineD3DSurface_LockRect(pCursorBitmap, &lockedRect, NULL,
5862                                          WINED3DLOCK_NO_DIRTY_UPDATE |
5863                                          WINED3DLOCK_READONLY
5864             );
5865             TRACE("width: %i height: %i\n", pSur->currentDesc.Width,
5866                   pSur->currentDesc.Height);
5867
5868             cursorInfo.fIcon = FALSE;
5869             cursorInfo.xHotspot = XHotSpot;
5870             cursorInfo.yHotspot = YHotSpot;
5871             cursorInfo.hbmMask = CreateBitmap(pSur->currentDesc.Width,
5872                                               pSur->currentDesc.Height, 1,
5873                                               1, &maskBits);
5874             cursorInfo.hbmColor = CreateBitmap(pSur->currentDesc.Width,
5875                                                pSur->currentDesc.Height, 1,
5876                                                32, lockedRect.pBits);
5877             IWineD3DSurface_UnlockRect(pCursorBitmap);
5878             /* Create our cursor and clean up. */
5879             cursor = CreateIconIndirect(&cursorInfo);
5880             SetCursor(cursor);
5881             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
5882             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
5883             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
5884             This->hardwareCursor = cursor;
5885             HeapFree(GetProcessHeap(), 0, maskBits);
5886         }
5887     }
5888
5889     This->xHotSpot = XHotSpot;
5890     This->yHotSpot = YHotSpot;
5891     return WINED3D_OK;
5892 }
5893
5894 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5895     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5896     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5897
5898     This->xScreenSpace = XScreenSpace;
5899     This->yScreenSpace = YScreenSpace;
5900
5901     return;
5902
5903 }
5904
5905 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5906     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5907     BOOL oldVisible = This->bCursorVisible;
5908     POINT pt;
5909
5910     TRACE("(%p) : visible(%d)\n", This, bShow);
5911
5912     /*
5913      * When ShowCursor is first called it should make the cursor appear at the OS's last
5914      * known cursor position.  Because of this, some applications just repetitively call
5915      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
5916      */
5917     GetCursorPos(&pt);
5918     This->xScreenSpace = pt.x;
5919     This->yScreenSpace = pt.y;
5920
5921     if (This->haveHardwareCursor) {
5922         This->bCursorVisible = bShow;
5923         if (bShow)
5924             SetCursor(This->hardwareCursor);
5925         else
5926             SetCursor(NULL);
5927     }
5928     else
5929     {
5930         if (This->cursorTexture)
5931             This->bCursorVisible = bShow;
5932     }
5933
5934     return oldVisible;
5935 }
5936
5937 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5938     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5939     TRACE("(%p) : state (%u)\n", This, This->state);
5940     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5941     switch (This->state) {
5942     case WINED3D_OK:
5943         return WINED3D_OK;
5944     case WINED3DERR_DEVICELOST:
5945         {
5946             ResourceList *resourceList  = This->resources;
5947             while (NULL != resourceList) {
5948                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5949                 return WINED3DERR_DEVICENOTRESET;
5950                 resourceList = resourceList->next;
5951             }
5952             return WINED3DERR_DEVICELOST;
5953         }
5954     case WINED3DERR_DRIVERINTERNALERROR:
5955         return WINED3DERR_DRIVERINTERNALERROR;
5956     }
5957
5958     /* Unknown state */
5959     return WINED3DERR_DRIVERINTERNALERROR;
5960 }
5961
5962
5963 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5964     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5965     /** FIXME: Resource tracking needs to be done,
5966     * The closes we can do to this is set the priorities of all managed textures low
5967     * and then reset them.
5968      ***********************************************************/
5969     FIXME("(%p) : stub\n", This);
5970     return WINED3D_OK;
5971 }
5972
5973 static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5974     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
5975
5976     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
5977     if(surface->Flags & SFLAG_DIBSECTION) {
5978         /* Release the DC */
5979         SelectObject(surface->hDC, surface->dib.holdbitmap);
5980         DeleteDC(surface->hDC);
5981         /* Release the DIB section */
5982         DeleteObject(surface->dib.DIBsection);
5983         surface->dib.bitmap_data = NULL;
5984         surface->resource.allocatedMemory = NULL;
5985         surface->Flags &= ~SFLAG_DIBSECTION;
5986     }
5987     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
5988     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
5989     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
5990         surface->pow2Width = pPresentationParameters->BackBufferWidth;
5991         surface->pow2Height = pPresentationParameters->BackBufferHeight;
5992     } else {
5993         surface->pow2Width = surface->pow2Height = 1;
5994         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
5995         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
5996     }
5997     if(surface->glDescription.textureName) {
5998         ENTER_GL();
5999         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
6000         glDeleteTextures(1, &surface->glDescription.textureName);
6001         LEAVE_GL();
6002         surface->glDescription.textureName = 0;
6003         surface->Flags &= ~SFLAG_CLIENT;
6004     }
6005     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
6006        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
6007         surface->Flags |= SFLAG_NONPOW2;
6008     } else  {
6009         surface->Flags &= ~SFLAG_NONPOW2;
6010     }
6011     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
6012     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6013 }
6014
6015 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6016     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6017     IWineD3DSwapChainImpl *swapchain;
6018     HRESULT hr;
6019     BOOL DisplayModeChanged = FALSE;
6020     WINED3DDISPLAYMODE mode;
6021     TRACE("(%p)\n", This);
6022
6023     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6024     if(FAILED(hr)) {
6025         ERR("Failed to get the first implicit swapchain\n");
6026         return hr;
6027     }
6028
6029     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6030      * on an existing gl context, so there's no real need for recreation.
6031      *
6032      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6033      *
6034      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6035      */
6036     TRACE("New params:\n");
6037     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
6038     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
6039     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
6040     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
6041     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
6042     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
6043     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
6044     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
6045     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
6046     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6047     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
6048     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
6049     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
6050
6051     /* No special treatment of these parameters. Just store them */
6052     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
6053     swapchain->presentParms.Flags = pPresentationParameters->Flags;
6054     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
6055     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
6056
6057     /* What to do about these? */
6058     if(pPresentationParameters->BackBufferCount != 0 &&
6059         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6060         ERR("Cannot change the back buffer count yet\n");
6061     }
6062     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6063         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6064         ERR("Cannot change the back buffer format yet\n");
6065     }
6066     if(pPresentationParameters->hDeviceWindow != NULL &&
6067         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6068         ERR("Cannot change the device window yet\n");
6069     }
6070     if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
6071         ERR("What do do about a changed auto depth stencil parameter?\n");
6072     }
6073
6074     if(pPresentationParameters->Windowed) {
6075         mode.Width = swapchain->orig_width;
6076         mode.Height = swapchain->orig_height;
6077         mode.RefreshRate = 0;
6078         mode.Format = swapchain->presentParms.BackBufferFormat;
6079     } else {
6080         mode.Width = pPresentationParameters->BackBufferWidth;
6081         mode.Height = pPresentationParameters->BackBufferHeight;
6082         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
6083         mode.Format = swapchain->presentParms.BackBufferFormat;
6084     }
6085
6086     /* Should Width == 800 && Height == 0 set 800x600? */
6087     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
6088        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6089         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6090     {
6091         WINED3DVIEWPORT vp;
6092         int i;
6093
6094         vp.X = 0;
6095         vp.Y = 0;
6096         vp.Width = pPresentationParameters->BackBufferWidth;
6097         vp.Height = pPresentationParameters->BackBufferHeight;
6098         vp.MinZ = 0;
6099         vp.MaxZ = 1;
6100
6101         if(!pPresentationParameters->Windowed) {
6102             DisplayModeChanged = TRUE;
6103         }
6104         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
6105         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
6106
6107         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
6108         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
6109             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
6110         }
6111
6112         /* Now set the new viewport */
6113         IWineD3DDevice_SetViewport(iface, &vp);
6114     }
6115
6116     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
6117        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
6118         DisplayModeChanged) {
6119
6120         /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
6121         if(!pPresentationParameters->Windowed) {
6122             IWineD3DDevice_SetFullscreen(iface, TRUE);
6123         }
6124
6125         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6126
6127         /* Switching out of fullscreen mode? First set the original res, then change the window */
6128         if(pPresentationParameters->Windowed) {
6129             IWineD3DDevice_SetFullscreen(iface, FALSE);
6130         }
6131         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
6132     }
6133
6134     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6135     return WINED3D_OK;
6136 }
6137
6138 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6139     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6140     /** FIXME: always true at the moment **/
6141     if(!bEnableDialogs) {
6142         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6143     }
6144     return WINED3D_OK;
6145 }
6146
6147
6148 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6149     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6150     TRACE("(%p) : pParameters %p\n", This, pParameters);
6151
6152     *pParameters = This->createParms;
6153     return WINED3D_OK;
6154 }
6155
6156 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6157     IWineD3DSwapChain *swapchain;
6158     HRESULT hrc = WINED3D_OK;
6159
6160     TRACE("Relaying  to swapchain\n");
6161
6162     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6163         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6164         IWineD3DSwapChain_Release(swapchain);
6165     }
6166     return;
6167 }
6168
6169 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6170     IWineD3DSwapChain *swapchain;
6171     HRESULT hrc = WINED3D_OK;
6172
6173     TRACE("Relaying  to swapchain\n");
6174
6175     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6176         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6177         IWineD3DSwapChain_Release(swapchain);
6178     }
6179     return;
6180 }
6181
6182
6183 /** ********************************************************
6184 *   Notification functions
6185 ** ********************************************************/
6186 /** This function must be called in the release of a resource when ref == 0,
6187 * the contents of resource must still be correct,
6188 * any handels to other resource held by the caller must be closed
6189 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6190  *****************************************************/
6191 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6192     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6193     ResourceList* resourceList;
6194
6195     TRACE("(%p) : resource %p\n", This, resource);
6196     /* add a new texture to the frot of the linked list */
6197     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6198     resourceList->resource = resource;
6199
6200     /* Get the old head */
6201     resourceList->next = This->resources;
6202
6203     This->resources = resourceList;
6204     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6205
6206     return;
6207 }
6208
6209 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6210     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6211     ResourceList* resourceList = NULL;
6212     ResourceList* previousResourceList = NULL;
6213     
6214     TRACE("(%p) : resource %p\n", This, resource);
6215
6216     resourceList = This->resources;
6217
6218     while (resourceList != NULL) {
6219         if(resourceList->resource == resource) break;
6220         previousResourceList = resourceList;
6221         resourceList = resourceList->next;
6222     }
6223
6224     if (resourceList == NULL) {
6225         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6226         return;
6227     } else {
6228             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6229     }
6230     /* make sure we don't leave a hole in the list */
6231     if (previousResourceList != NULL) {
6232         previousResourceList->next = resourceList->next;
6233     } else {
6234         This->resources = resourceList->next;
6235     }
6236
6237     return;
6238 }
6239
6240
6241 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6242     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6243     int counter;
6244
6245     TRACE("(%p) : resource %p\n", This, resource);
6246     switch(IWineD3DResource_GetType(resource)){
6247         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6248         case WINED3DRTYPE_SURFACE: {
6249             unsigned int i;
6250
6251             /* Cleanup any FBO attachments */
6252             for (i = 0; i < GL_LIMITS(buffers); ++i) {
6253                 if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) {
6254                     bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6255                     set_render_target_fbo(iface, i, NULL);
6256                     This->fbo_color_attachments[i] = NULL;
6257                 }
6258             }
6259             if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) {
6260                 bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6261                 set_depth_stencil_fbo(iface, NULL);
6262                 This->fbo_depth_attachment = NULL;
6263             }
6264
6265             break;
6266         }
6267
6268         case WINED3DRTYPE_TEXTURE:
6269         case WINED3DRTYPE_CUBETEXTURE:
6270         case WINED3DRTYPE_VOLUMETEXTURE:
6271                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
6272                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6273                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6274                         This->stateBlock->textures[counter] = NULL;
6275                     }
6276                     if (This->updateStateBlock != This->stateBlock ){
6277                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6278                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6279                             This->updateStateBlock->textures[counter] = NULL;
6280                         }
6281                     }
6282                 }
6283         break;
6284         case WINED3DRTYPE_VOLUME:
6285         /* TODO: nothing really? */
6286         break;
6287         case WINED3DRTYPE_VERTEXBUFFER:
6288         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6289         {
6290             int streamNumber;
6291             TRACE("Cleaning up stream pointers\n");
6292
6293             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6294                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6295                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6296                 */
6297                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6298                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6299                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6300                         This->updateStateBlock->streamSource[streamNumber] = 0;
6301                         /* Set changed flag? */
6302                     }
6303                 }
6304                 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) */
6305                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6306                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6307                         This->stateBlock->streamSource[streamNumber] = 0;
6308                     }
6309                 }
6310 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6311                  else { /* This shouldn't happen */
6312                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6313                 }
6314 #endif
6315
6316             }
6317         }
6318         break;
6319         case WINED3DRTYPE_INDEXBUFFER:
6320         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6321         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6322             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6323                 This->updateStateBlock->pIndexData =  NULL;
6324             }
6325         }
6326         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6327             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6328                 This->stateBlock->pIndexData =  NULL;
6329             }
6330         }
6331
6332         break;
6333         default:
6334         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6335         break;
6336     }
6337
6338
6339     /* Remove the resoruce from the resourceStore */
6340     IWineD3DDeviceImpl_RemoveResource(iface, resource);
6341
6342     TRACE("Resource released\n");
6343
6344 }
6345
6346 /**********************************************************
6347  * IWineD3DDevice VTbl follows
6348  **********************************************************/
6349
6350 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6351 {
6352     /*** IUnknown methods ***/
6353     IWineD3DDeviceImpl_QueryInterface,
6354     IWineD3DDeviceImpl_AddRef,
6355     IWineD3DDeviceImpl_Release,
6356     /*** IWineD3DDevice methods ***/
6357     IWineD3DDeviceImpl_GetParent,
6358     /*** Creation methods**/
6359     IWineD3DDeviceImpl_CreateVertexBuffer,
6360     IWineD3DDeviceImpl_CreateIndexBuffer,
6361     IWineD3DDeviceImpl_CreateStateBlock,
6362     IWineD3DDeviceImpl_CreateSurface,
6363     IWineD3DDeviceImpl_CreateTexture,
6364     IWineD3DDeviceImpl_CreateVolumeTexture,
6365     IWineD3DDeviceImpl_CreateVolume,
6366     IWineD3DDeviceImpl_CreateCubeTexture,
6367     IWineD3DDeviceImpl_CreateQuery,
6368     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6369     IWineD3DDeviceImpl_CreateVertexDeclaration,
6370     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
6371     IWineD3DDeviceImpl_CreateVertexShader,
6372     IWineD3DDeviceImpl_CreatePixelShader,
6373     IWineD3DDeviceImpl_CreatePalette,
6374     /*** Odd functions **/
6375     IWineD3DDeviceImpl_Init3D,
6376     IWineD3DDeviceImpl_Uninit3D,
6377     IWineD3DDeviceImpl_SetFullscreen,
6378     IWineD3DDeviceImpl_SetMultithreaded,
6379     IWineD3DDeviceImpl_EvictManagedResources,
6380     IWineD3DDeviceImpl_GetAvailableTextureMem,
6381     IWineD3DDeviceImpl_GetBackBuffer,
6382     IWineD3DDeviceImpl_GetCreationParameters,
6383     IWineD3DDeviceImpl_GetDeviceCaps,
6384     IWineD3DDeviceImpl_GetDirect3D,
6385     IWineD3DDeviceImpl_GetDisplayMode,
6386     IWineD3DDeviceImpl_SetDisplayMode,
6387     IWineD3DDeviceImpl_GetHWND,
6388     IWineD3DDeviceImpl_SetHWND,
6389     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6390     IWineD3DDeviceImpl_GetRasterStatus,
6391     IWineD3DDeviceImpl_GetSwapChain,
6392     IWineD3DDeviceImpl_Reset,
6393     IWineD3DDeviceImpl_SetDialogBoxMode,
6394     IWineD3DDeviceImpl_SetCursorProperties,
6395     IWineD3DDeviceImpl_SetCursorPosition,
6396     IWineD3DDeviceImpl_ShowCursor,
6397     IWineD3DDeviceImpl_TestCooperativeLevel,
6398     /*** Getters and setters **/
6399     IWineD3DDeviceImpl_SetClipPlane,
6400     IWineD3DDeviceImpl_GetClipPlane,
6401     IWineD3DDeviceImpl_SetClipStatus,
6402     IWineD3DDeviceImpl_GetClipStatus,
6403     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6404     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6405     IWineD3DDeviceImpl_SetDepthStencilSurface,
6406     IWineD3DDeviceImpl_GetDepthStencilSurface,
6407     IWineD3DDeviceImpl_SetFVF,
6408     IWineD3DDeviceImpl_GetFVF,
6409     IWineD3DDeviceImpl_SetGammaRamp,
6410     IWineD3DDeviceImpl_GetGammaRamp,
6411     IWineD3DDeviceImpl_SetIndices,
6412     IWineD3DDeviceImpl_GetIndices,
6413     IWineD3DDeviceImpl_SetBaseVertexIndex,
6414     IWineD3DDeviceImpl_GetBaseVertexIndex,
6415     IWineD3DDeviceImpl_SetLight,
6416     IWineD3DDeviceImpl_GetLight,
6417     IWineD3DDeviceImpl_SetLightEnable,
6418     IWineD3DDeviceImpl_GetLightEnable,
6419     IWineD3DDeviceImpl_SetMaterial,
6420     IWineD3DDeviceImpl_GetMaterial,
6421     IWineD3DDeviceImpl_SetNPatchMode,
6422     IWineD3DDeviceImpl_GetNPatchMode,
6423     IWineD3DDeviceImpl_SetPaletteEntries,
6424     IWineD3DDeviceImpl_GetPaletteEntries,
6425     IWineD3DDeviceImpl_SetPixelShader,
6426     IWineD3DDeviceImpl_GetPixelShader,
6427     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6428     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6429     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6430     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6431     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6432     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6433     IWineD3DDeviceImpl_SetRenderState,
6434     IWineD3DDeviceImpl_GetRenderState,
6435     IWineD3DDeviceImpl_SetRenderTarget,
6436     IWineD3DDeviceImpl_GetRenderTarget,
6437     IWineD3DDeviceImpl_SetFrontBackBuffers,
6438     IWineD3DDeviceImpl_SetSamplerState,
6439     IWineD3DDeviceImpl_GetSamplerState,
6440     IWineD3DDeviceImpl_SetScissorRect,
6441     IWineD3DDeviceImpl_GetScissorRect,
6442     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6443     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6444     IWineD3DDeviceImpl_SetStreamSource,
6445     IWineD3DDeviceImpl_GetStreamSource,
6446     IWineD3DDeviceImpl_SetStreamSourceFreq,
6447     IWineD3DDeviceImpl_GetStreamSourceFreq,
6448     IWineD3DDeviceImpl_SetTexture,
6449     IWineD3DDeviceImpl_GetTexture,
6450     IWineD3DDeviceImpl_SetTextureStageState,
6451     IWineD3DDeviceImpl_GetTextureStageState,
6452     IWineD3DDeviceImpl_SetTransform,
6453     IWineD3DDeviceImpl_GetTransform,
6454     IWineD3DDeviceImpl_SetVertexDeclaration,
6455     IWineD3DDeviceImpl_GetVertexDeclaration,
6456     IWineD3DDeviceImpl_SetVertexShader,
6457     IWineD3DDeviceImpl_GetVertexShader,
6458     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6459     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6460     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6461     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6462     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6463     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6464     IWineD3DDeviceImpl_SetViewport,
6465     IWineD3DDeviceImpl_GetViewport,
6466     IWineD3DDeviceImpl_MultiplyTransform,
6467     IWineD3DDeviceImpl_ValidateDevice,
6468     IWineD3DDeviceImpl_ProcessVertices,
6469     /*** State block ***/
6470     IWineD3DDeviceImpl_BeginStateBlock,
6471     IWineD3DDeviceImpl_EndStateBlock,
6472     /*** Scene management ***/
6473     IWineD3DDeviceImpl_BeginScene,
6474     IWineD3DDeviceImpl_EndScene,
6475     IWineD3DDeviceImpl_Present,
6476     IWineD3DDeviceImpl_Clear,
6477     /*** Drawing ***/
6478     IWineD3DDeviceImpl_DrawPrimitive,
6479     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6480     IWineD3DDeviceImpl_DrawPrimitiveUP,
6481     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6482     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6483     IWineD3DDeviceImpl_DrawRectPatch,
6484     IWineD3DDeviceImpl_DrawTriPatch,
6485     IWineD3DDeviceImpl_DeletePatch,
6486     IWineD3DDeviceImpl_ColorFill,
6487     IWineD3DDeviceImpl_UpdateTexture,
6488     IWineD3DDeviceImpl_UpdateSurface,
6489     IWineD3DDeviceImpl_GetFrontBufferData,
6490     /*** object tracking ***/
6491     IWineD3DDeviceImpl_ResourceReleased
6492 };
6493
6494
6495 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6496     WINED3DRS_ALPHABLENDENABLE   ,
6497     WINED3DRS_ALPHAFUNC          ,
6498     WINED3DRS_ALPHAREF           ,
6499     WINED3DRS_ALPHATESTENABLE    ,
6500     WINED3DRS_BLENDOP            ,
6501     WINED3DRS_COLORWRITEENABLE   ,
6502     WINED3DRS_DESTBLEND          ,
6503     WINED3DRS_DITHERENABLE       ,
6504     WINED3DRS_FILLMODE           ,
6505     WINED3DRS_FOGDENSITY         ,
6506     WINED3DRS_FOGEND             ,
6507     WINED3DRS_FOGSTART           ,
6508     WINED3DRS_LASTPIXEL          ,
6509     WINED3DRS_SHADEMODE          ,
6510     WINED3DRS_SRCBLEND           ,
6511     WINED3DRS_STENCILENABLE      ,
6512     WINED3DRS_STENCILFAIL        ,
6513     WINED3DRS_STENCILFUNC        ,
6514     WINED3DRS_STENCILMASK        ,
6515     WINED3DRS_STENCILPASS        ,
6516     WINED3DRS_STENCILREF         ,
6517     WINED3DRS_STENCILWRITEMASK   ,
6518     WINED3DRS_STENCILZFAIL       ,
6519     WINED3DRS_TEXTUREFACTOR      ,
6520     WINED3DRS_WRAP0              ,
6521     WINED3DRS_WRAP1              ,
6522     WINED3DRS_WRAP2              ,
6523     WINED3DRS_WRAP3              ,
6524     WINED3DRS_WRAP4              ,
6525     WINED3DRS_WRAP5              ,
6526     WINED3DRS_WRAP6              ,
6527     WINED3DRS_WRAP7              ,
6528     WINED3DRS_ZENABLE            ,
6529     WINED3DRS_ZFUNC              ,
6530     WINED3DRS_ZWRITEENABLE
6531 };
6532
6533 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6534     WINED3DTSS_ADDRESSW              ,
6535     WINED3DTSS_ALPHAARG0             ,
6536     WINED3DTSS_ALPHAARG1             ,
6537     WINED3DTSS_ALPHAARG2             ,
6538     WINED3DTSS_ALPHAOP               ,
6539     WINED3DTSS_BUMPENVLOFFSET        ,
6540     WINED3DTSS_BUMPENVLSCALE         ,
6541     WINED3DTSS_BUMPENVMAT00          ,
6542     WINED3DTSS_BUMPENVMAT01          ,
6543     WINED3DTSS_BUMPENVMAT10          ,
6544     WINED3DTSS_BUMPENVMAT11          ,
6545     WINED3DTSS_COLORARG0             ,
6546     WINED3DTSS_COLORARG1             ,
6547     WINED3DTSS_COLORARG2             ,
6548     WINED3DTSS_COLOROP               ,
6549     WINED3DTSS_RESULTARG             ,
6550     WINED3DTSS_TEXCOORDINDEX         ,
6551     WINED3DTSS_TEXTURETRANSFORMFLAGS
6552 };
6553
6554 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6555     WINED3DSAMP_ADDRESSU         ,
6556     WINED3DSAMP_ADDRESSV         ,
6557     WINED3DSAMP_ADDRESSW         ,
6558     WINED3DSAMP_BORDERCOLOR      ,
6559     WINED3DSAMP_MAGFILTER        ,
6560     WINED3DSAMP_MINFILTER        ,
6561     WINED3DSAMP_MIPFILTER        ,
6562     WINED3DSAMP_MIPMAPLODBIAS    ,
6563     WINED3DSAMP_MAXMIPLEVEL      ,
6564     WINED3DSAMP_MAXANISOTROPY    ,
6565     WINED3DSAMP_SRGBTEXTURE      ,
6566     WINED3DSAMP_ELEMENTINDEX
6567 };
6568
6569 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6570     WINED3DRS_AMBIENT                       ,
6571     WINED3DRS_AMBIENTMATERIALSOURCE         ,
6572     WINED3DRS_CLIPPING                      ,
6573     WINED3DRS_CLIPPLANEENABLE               ,
6574     WINED3DRS_COLORVERTEX                   ,
6575     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
6576     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
6577     WINED3DRS_FOGDENSITY                    ,
6578     WINED3DRS_FOGEND                        ,
6579     WINED3DRS_FOGSTART                      ,
6580     WINED3DRS_FOGTABLEMODE                  ,
6581     WINED3DRS_FOGVERTEXMODE                 ,
6582     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
6583     WINED3DRS_LIGHTING                      ,
6584     WINED3DRS_LOCALVIEWER                   ,
6585     WINED3DRS_MULTISAMPLEANTIALIAS          ,
6586     WINED3DRS_MULTISAMPLEMASK               ,
6587     WINED3DRS_NORMALIZENORMALS              ,
6588     WINED3DRS_PATCHEDGESTYLE                ,
6589     WINED3DRS_POINTSCALE_A                  ,
6590     WINED3DRS_POINTSCALE_B                  ,
6591     WINED3DRS_POINTSCALE_C                  ,
6592     WINED3DRS_POINTSCALEENABLE              ,
6593     WINED3DRS_POINTSIZE                     ,
6594     WINED3DRS_POINTSIZE_MAX                 ,
6595     WINED3DRS_POINTSIZE_MIN                 ,
6596     WINED3DRS_POINTSPRITEENABLE             ,
6597     WINED3DRS_RANGEFOGENABLE                ,
6598     WINED3DRS_SPECULARMATERIALSOURCE        ,
6599     WINED3DRS_TWEENFACTOR                   ,
6600     WINED3DRS_VERTEXBLEND
6601 };
6602
6603 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6604     WINED3DTSS_TEXCOORDINDEX         ,
6605     WINED3DTSS_TEXTURETRANSFORMFLAGS
6606 };
6607
6608 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6609     WINED3DSAMP_DMAPOFFSET
6610 };
6611
6612 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
6613     DWORD rep = StateTable[state].representative;
6614     DWORD idx;
6615     BYTE shift;
6616     UINT i;
6617     WineD3DContext *context;
6618
6619     if(!rep) return;
6620     for(i = 0; i < This->numContexts; i++) {
6621         context = This->contexts[i];
6622         if(isStateDirty(context, rep)) continue;
6623
6624         context->dirtyArray[context->numDirtyEntries++] = rep;
6625         idx = rep >> 5;
6626         shift = rep & 0x1f;
6627         context->isStateDirty[idx] |= (1 << shift);
6628     }
6629 }