rpcrt4: Fix bug calculating union switch type.
[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 }
144
145 /**********************************************************
146  * Global variable / Constants follow
147  **********************************************************/
148 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
149
150 /**********************************************************
151  * IUnknown parts follows
152  **********************************************************/
153
154 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
155 {
156     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
157
158     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
159     if (IsEqualGUID(riid, &IID_IUnknown)
160         || IsEqualGUID(riid, &IID_IWineD3DBase)
161         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
162         IUnknown_AddRef(iface);
163         *ppobj = This;
164         return S_OK;
165     }
166     *ppobj = NULL;
167     return E_NOINTERFACE;
168 }
169
170 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
171     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
172     ULONG refCount = InterlockedIncrement(&This->ref);
173
174     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
175     return refCount;
176 }
177
178 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
179     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
180     ULONG refCount = InterlockedDecrement(&This->ref);
181
182     TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
183
184     if (!refCount) {
185         if (This->fbo) {
186             GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
187         }
188         if (This->src_fbo) {
189             GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->src_fbo));
190         }
191         if (This->dst_fbo) {
192             GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->dst_fbo));
193         }
194
195         HeapFree(GetProcessHeap(), 0, This->render_targets);
196         HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments);
197         HeapFree(GetProcessHeap(), 0, This->draw_buffers);
198
199         if (This->glsl_program_lookup) hash_table_destroy(This->glsl_program_lookup);
200
201         /* TODO: Clean up all the surfaces and textures! */
202         /* NOTE: You must release the parent if the object was created via a callback
203         ** ***************************/
204
205         /* Release the update stateblock */
206         if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
207             if(This->updateStateBlock != This->stateBlock)
208                 FIXME("(%p) Something's still holding the Update stateblock\n",This);
209         }
210         This->updateStateBlock = NULL;
211         { /* because were not doing proper internal refcounts releasing the primary state block
212             causes recursion with the extra checks in ResourceReleased, to avoid this we have
213             to set this->stateBlock = NULL; first */
214             IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
215             This->stateBlock = NULL;
216
217             /* Release the stateblock */
218             if(IWineD3DStateBlock_Release(stateBlock) > 0){
219                     FIXME("(%p) Something's still holding the Update stateblock\n",This);
220             }
221         }
222
223         if (This->resources != NULL ) {
224             FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
225             dumpResources(This->resources);
226         }
227
228         if(This->contexts) ERR("Context array not freed!\n");
229         if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
230         This->haveHardwareCursor = FALSE;
231
232         IWineD3D_Release(This->wineD3D);
233         This->wineD3D = NULL;
234         HeapFree(GetProcessHeap(), 0, This);
235         TRACE("Freed device  %p\n", This);
236         This = NULL;
237     }
238     return refCount;
239 }
240
241 /**********************************************************
242  * IWineD3DDevice implementation follows
243  **********************************************************/
244 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
245     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
246     *pParent = This->parent;
247     IUnknown_AddRef(This->parent);
248     return WINED3D_OK;
249 }
250
251 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
252     IWineD3DDeviceImpl *This = object->resource.wineD3DDevice;  /* Needed for GL_EXTCALL */
253     GLenum error, glUsage;
254     DWORD vboUsage = object->resource.usage;
255     if(object->Flags & VBFLAG_VBOCREATEFAIL) {
256         WARN("Creating a vbo failed once, not trying again\n");
257         return;
258     }
259
260     TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p  Usage(%s)\n", object, debug_d3dusage(vboUsage));
261
262     ENTER_GL();
263     /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
264     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
265
266     /* Make sure that the gl error is cleared. Do not use checkGLcall
267       * here because checkGLcall just prints a fixme and continues. However,
268       * if an error during VBO creation occurs we can fall back to non-vbo operation
269       * with full functionality(but performance loss)
270       */
271     while(glGetError() != GL_NO_ERROR);
272
273     /* Basically the FVF parameter passed to CreateVertexBuffer is no good
274       * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
275       * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
276       * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
277       * to check if the rhw and color values are in the correct format.
278       */
279
280     GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
281     error = glGetError();
282     if(object->vbo == 0 || error != GL_NO_ERROR) {
283         WARN("Failed to create a VBO with error %s (%#x)\n", debug_glerror(error), error);
284         goto error;
285     }
286
287     GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
288     error = glGetError();
289     if(error != GL_NO_ERROR) {
290         WARN("Failed to bind the VBO with error %s (%#x)\n", debug_glerror(error), error);
291         goto error;
292     }
293
294     /* Don't use static, because dx apps tend to update the buffer
295      * quite often even if they specify 0 usage. Because we always keep the local copy
296      * we never read from the vbo and can create a write only opengl buffer.
297      */
298     switch(vboUsage & (WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC) ) {
299         case WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC:
300         case WINED3DUSAGE_DYNAMIC:
301             TRACE("Gl usage = GL_STREAM_DRAW\n");
302             glUsage = GL_STREAM_DRAW_ARB;
303             break;
304         case WINED3DUSAGE_WRITEONLY:
305         default:
306             TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
307             glUsage = GL_DYNAMIC_DRAW_ARB;
308             break;
309     }
310
311     /* Reserve memory for the buffer. The amount of data won't change
312      * so we are safe with calling glBufferData once with a NULL ptr and
313      * calling glBufferSubData on updates
314      */
315     GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
316     error = glGetError();
317     if(error != GL_NO_ERROR) {
318         WARN("glBufferDataARB failed with error %s (%#x)\n", debug_glerror(error), error);
319         goto error;
320     }
321
322     LEAVE_GL();
323
324     return;
325     error:
326     /* Clean up all vbo init, but continue because we can work without a vbo :-) */
327     FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
328     if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
329     object->vbo = 0;
330     object->Flags |= VBFLAG_VBOCREATEFAIL;
331     LEAVE_GL();
332     return;
333 }
334
335 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, 
336                              DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
337                              IUnknown *parent) {
338     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
339     IWineD3DVertexBufferImpl *object;
340     WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
341     int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
342     BOOL conv;
343
344     if(Size == 0) {
345         WARN("Size 0 requested, returning WINED3DERR_INVALIDCALL\n");
346         *ppVertexBuffer = NULL;
347         return WINED3DERR_INVALIDCALL;
348     }
349
350     D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
351
352     TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
353     *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
354
355     if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
356         object->resource.allocatedMemory  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
357     }
358     object->fvf = FVF;
359
360     /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
361      * drawStridedFast (half-life 2).
362      *
363      * Basically converting the vertices in the buffer is quite expensive, and observations
364      * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
365      * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
366      *
367      * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
368      * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
369      * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
370      * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
371      * dx7 apps.
372      * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
373      * more. In this call we can convert dx7 buffers too.
374      */
375     conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
376     if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && 
377         (dxVersion > 7 || !conv) ) {
378         CreateVBO(object);
379     }
380     return WINED3D_OK;
381 }
382
383 static void CreateIndexBufferVBO(IWineD3DDeviceImpl *This, IWineD3DIndexBufferImpl *object) {
384     GLenum error, glUsage;
385     TRACE("Creating VBO for Index Buffer %p\n", object);
386
387     /* The following code will modify the ELEMENT_ARRAY_BUFFER binding, make sure it is
388      * restored on the next draw
389      */
390     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
391
392     ENTER_GL();
393     /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
394     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
395
396     while(glGetError());
397
398     GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
399     error = glGetError();
400     if(error != GL_NO_ERROR || object->vbo == 0) {
401         ERR("Creating a vbo failed with error %s (%#x), continuing without vbo for this buffer\n", debug_glerror(error), error);
402         goto out;
403     }
404
405     GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->vbo));
406     error = glGetError();
407     if(error != GL_NO_ERROR) {
408         ERR("Failed to bind index buffer with error %s (%#x), continuing without vbo for this buffer\n", debug_glerror(error), error);
409         goto out;
410     }
411
412     /* Use static write only usage for now. Dynamic index buffers stay in sysmem, and due to the sysmem
413         * copy no readback will be needed
414         */
415     glUsage = GL_STATIC_DRAW_ARB;
416     GL_EXTCALL(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
417     error = glGetError();
418     if(error != GL_NO_ERROR) {
419         ERR("Failed to initialize the index buffer with error %s (%#x)\n", debug_glerror(error), error);
420         goto out;
421     }
422     LEAVE_GL();
423     TRACE("Successfully created vbo %d for index buffer %p\n", object->vbo, object);
424     return;
425
426 out:
427     GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
428     GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
429     LEAVE_GL();
430     object->vbo = 0;
431 }
432
433 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage, 
434                                                     WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
435                                                     HANDLE *sharedHandle, IUnknown *parent) {
436     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
437     IWineD3DIndexBufferImpl *object;
438     TRACE("(%p) Creating index buffer\n", This);
439
440     /* Allocate the storage for the device */
441     D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
442
443     if (Pool == WINED3DPOOL_DEFAULT ) { /* We need a local copy for drawStridedSlow */
444         object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
445     }
446
447     if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
448         CreateIndexBufferVBO(This, object);
449     }
450
451     TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format, 
452                            debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
453     *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
454
455     return WINED3D_OK;
456 }
457
458 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
459
460     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
461     IWineD3DStateBlockImpl *object;
462     int i, j;
463     HRESULT temp_result;
464
465     D3DCREATEOBJECTINSTANCE(object, StateBlock)
466     object->blockType     = Type;
467
468     for(i = 0; i < LIGHTMAP_SIZE; i++) {
469         list_init(&object->lightMap[i]);
470     }
471
472     /* Special case - Used during initialization to produce a placeholder stateblock
473           so other functions called can update a state block                         */
474     if (Type == WINED3DSBT_INIT) {
475         /* Don't bother increasing the reference count otherwise a device will never
476            be freed due to circular dependencies                                   */
477         return WINED3D_OK;
478     }
479     
480     temp_result = allocate_shader_constants(object);
481     if (WINED3D_OK != temp_result)
482         return temp_result;
483
484     /* Otherwise, might as well set the whole state block to the appropriate values  */
485     if (This->stateBlock != NULL)
486         stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
487     else
488         memset(object->streamFreq, 1, sizeof(object->streamFreq));
489
490     /* Reset the ref and type after kludging it */
491     object->wineD3DDevice = This;
492     object->ref           = 1;
493     object->blockType     = Type;
494
495     TRACE("Updating changed flags appropriate for type %d\n", Type);
496
497     if (Type == WINED3DSBT_ALL) {
498
499         TRACE("ALL => Pretend everything has changed\n");
500         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
501
502         /* Lights are not part of the changed / set structure */
503         for(j = 0; j < LIGHTMAP_SIZE; j++) {
504             struct list *e;
505             LIST_FOR_EACH(e, &object->lightMap[j]) {
506                 PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
507                 light->changed = TRUE;
508                 light->enabledChanged = TRUE;
509             }
510         }
511     } else if (Type == WINED3DSBT_PIXELSTATE) {
512
513         TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
514         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
515
516         object->changed.pixelShader = TRUE;
517
518         /* Pixel Shader Constants */
519         for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
520             object->changed.pixelShaderConstantsF[i] = TRUE;
521         for (i = 0; i < MAX_CONST_B; ++i)
522             object->changed.pixelShaderConstantsB[i] = TRUE;
523         for (i = 0; i < MAX_CONST_I; ++i)
524             object->changed.pixelShaderConstantsI[i] = TRUE;
525         
526         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
527             object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
528         }
529         for (j = 0; j < GL_LIMITS(texture_stages); j++) {
530             for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
531                 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
532             }
533         }
534         for (j = 0 ; j < 16; j++) {
535             for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
536
537                 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
538             }
539         }
540
541     } else if (Type == WINED3DSBT_VERTEXSTATE) {
542
543         TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
544         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
545
546         object->changed.vertexShader = TRUE;
547
548         /* Vertex Shader Constants */
549         for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
550             object->changed.vertexShaderConstantsF[i] = TRUE;
551         for (i = 0; i < MAX_CONST_B; ++i)
552             object->changed.vertexShaderConstantsB[i] = TRUE;
553         for (i = 0; i < MAX_CONST_I; ++i)
554             object->changed.vertexShaderConstantsI[i] = TRUE;
555  
556         for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
557             object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
558         }
559         for (j = 0; j < GL_LIMITS(texture_stages); j++) {
560             for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
561                 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
562             }
563         }
564         for (j = 0 ; j < 16; j++){
565             for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
566                 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
567             }
568         }
569
570         for(j = 0; j < LIGHTMAP_SIZE; j++) {
571             struct list *e;
572             LIST_FOR_EACH(e, &object->lightMap[j]) {
573                 PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
574                 light->changed = TRUE;
575                 light->enabledChanged = TRUE;
576             }
577         }
578     } else {
579         FIXME("Unrecognized state block type %d\n", Type);
580     }
581
582     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
583     return WINED3D_OK;
584 }
585
586 /* ************************************
587 MSDN:
588 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
589
590 Discard
591  [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. 
592
593 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.
594
595 ******************************** */
596  
597 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) {
598     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;    
599     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
600     unsigned int pow2Width, pow2Height;
601     unsigned int Size       = 1;
602     const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
603     TRACE("(%p) Create surface\n",This);
604     
605     /** FIXME: Check ranges on the inputs are valid 
606      * MSDN
607      *   MultisampleQuality
608      *    [in] Quality level. The valid range is between zero and one less than the level
609      *    returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. 
610      *    Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
611      *    values of paired render targets, depth stencil surfaces, and the MultiSample type
612      *    must all match.
613       *******************************/
614
615
616     /**
617     * TODO: Discard MSDN
618     * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
619     *
620     * If this flag is set, the contents of the depth stencil buffer will be
621     * invalid after calling either IDirect3DDevice9::Present or  * IDirect3DDevice9::SetDepthStencilSurface
622     * with a different depth surface.
623     *
624     *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
625     ***************************/
626
627     if(MultisampleQuality < 0) {
628         FIXME("Invalid multisample level %d\n", MultisampleQuality);
629         return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
630     }
631
632     if(MultisampleQuality > 0) {
633         FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
634         MultisampleQuality=0;
635     }
636
637     /** FIXME: Check that the format is supported
638     *    by the device.
639       *******************************/
640
641     /* Non-power2 support */
642     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
643         pow2Width = Width;
644         pow2Height = Height;
645     } else {
646         /* Find the nearest pow2 match */
647         pow2Width = pow2Height = 1;
648         while (pow2Width < Width) pow2Width <<= 1;
649         while (pow2Height < Height) pow2Height <<= 1;
650     }
651
652     if (pow2Width > Width || pow2Height > Height) {
653          /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
654         if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
655                || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
656             FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
657                     This, Width, Height);
658             return WINED3DERR_NOTAVAILABLE;
659         }
660     }
661
662     /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
663      *  it is based around 4x4 pixel blocks it requires padding, so allocate enough
664      *  space!
665       *********************************/
666     if (WINED3DFMT_UNKNOWN == Format) {
667         Size = 0;
668     } else if (Format == WINED3DFMT_DXT1) {
669         /* DXT1 is half byte per pixel */
670        Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4)) >> 1;
671
672     } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
673                Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
674        Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4));
675     } else {
676        /* The pitch is a multiple of 4 bytes */
677         Size = ((Width * tableEntry->bpp) + This->surface_alignment - 1) & ~(This->surface_alignment - 1);
678        Size *= Height;
679     }
680
681     /** Create and initialise the surface resource **/
682     D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
683     /* "Standalone" surface */
684     IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
685
686     object->currentDesc.Width      = Width;
687     object->currentDesc.Height     = Height;
688     object->currentDesc.MultiSampleType    = MultiSample;
689     object->currentDesc.MultiSampleQuality = MultisampleQuality;
690
691     /* Setup some glformat defaults */
692     object->glDescription.glFormat         = tableEntry->glFormat;
693     object->glDescription.glFormatInternal = tableEntry->glInternal;
694     object->glDescription.glType           = tableEntry->glType;
695
696     object->glDescription.textureName      = 0;
697     object->glDescription.level            = Level;
698     object->glDescription.target           = GL_TEXTURE_2D;
699
700     /* Internal data */
701     object->pow2Width  = pow2Width;
702     object->pow2Height = pow2Height;
703
704     /* Flags */
705     object->Flags      = 0;
706     object->Flags     |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
707     object->Flags     |= Discard ? SFLAG_DISCARD : 0;
708     object->Flags     |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
709     object->Flags     |= Lockable ? SFLAG_LOCKABLE : 0;
710
711
712     if (WINED3DFMT_UNKNOWN != Format) {
713         object->bytesPerPixel = tableEntry->bpp;
714     } else {
715         object->bytesPerPixel = 0;
716     }
717
718     /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
719
720     TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
721
722     /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
723     * this function is too deep to need to care about things like this.
724     * Levels need to be checked too, and possibly Type since they all affect what can be done.
725     * ****************************************/
726     switch(Pool) {
727     case WINED3DPOOL_SCRATCH:
728         if(!Lockable)
729             FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE "
730                 "which are mutually exclusive, setting lockable to TRUE\n");
731                 Lockable = TRUE;
732     break;
733     case WINED3DPOOL_SYSTEMMEM:
734         if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, "
735                                     "this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
736     case WINED3DPOOL_MANAGED:
737         if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a "
738                                                 "Usage of DYNAMIC which are mutually exclusive, not doing "
739                                                 "anything just telling you.\n");
740     break;
741     case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
742         if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
743            && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
744             WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
745     break;
746     default:
747         FIXME("(%p) Unknown pool %d\n", This, Pool);
748     break;
749     };
750
751     if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
752         FIXME("Trying to create a render target that isn't in the default pool\n");
753     }
754
755     /* mark the texture as dirty so that it gets loaded first time around*/
756     IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
757     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
758            This, Width, Height, Format, debug_d3dformat(Format),
759            (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
760
761     /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
762     if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
763         This->ddraw_primary = (IWineD3DSurface *) object;
764
765     /* Look at the implementation and set the correct Vtable */
766     switch(Impl) {
767         case SURFACE_OPENGL:
768             /* Nothing to do, it's set already */
769             break;
770
771         case SURFACE_GDI:
772             object->lpVtbl = &IWineGDISurface_Vtbl;
773             break;
774
775         default:
776             /* To be sure to catch this */
777             ERR("Unknown requested surface implementation %d!\n", Impl);
778             IWineD3DSurface_Release((IWineD3DSurface *) object);
779             return WINED3DERR_INVALIDCALL;
780     }
781
782     list_init(&object->renderbuffers);
783
784     /* Call the private setup routine */
785     return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
786
787 }
788
789 static HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
790                                                  DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
791                                                  IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
792                                                  D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
793
794     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
795     IWineD3DTextureImpl *object;
796     unsigned int i;
797     UINT tmpW;
798     UINT tmpH;
799     HRESULT hr;
800     unsigned int pow2Width;
801     unsigned int pow2Height;
802
803
804     TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
805     TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
806             Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
807
808     /* TODO: It should only be possible to create textures for formats 
809              that are reported as supported */
810     if (WINED3DFMT_UNKNOWN >= Format) {
811         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
812         return WINED3DERR_INVALIDCALL;
813     }
814
815     D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
816     D3DINITIALIZEBASETEXTURE(object->baseTexture);    
817     object->width  = Width;
818     object->height = Height;
819
820     /** Non-power2 support **/
821     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
822         pow2Width = Width;
823         pow2Height = Height;
824     } else {
825         /* Find the nearest pow2 match */
826         pow2Width = pow2Height = 1;
827         while (pow2Width < Width) pow2Width <<= 1;
828         while (pow2Height < Height) pow2Height <<= 1;
829     }
830
831     /** FIXME: add support for real non-power-two if it's provided by the video card **/
832     /* Precalculated scaling for 'faked' non power of two texture coords */
833     object->pow2scalingFactorX  =  (((float)Width)  / ((float)pow2Width));
834     object->pow2scalingFactorY  =  (((float)Height) / ((float)pow2Height));
835     TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
836
837     /* Calculate levels for mip mapping */
838     if (Levels == 0) {
839         TRACE("calculating levels %d\n", object->baseTexture.levels);
840         object->baseTexture.levels++;
841         tmpW = Width;
842         tmpH = Height;
843         while (tmpW > 1 || tmpH > 1) {
844             tmpW = max(1, tmpW >> 1);
845             tmpH = max(1, tmpH >> 1);
846             object->baseTexture.levels++;
847         }
848         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
849     }
850
851     /* Generate all the surfaces */
852     tmpW = Width;
853     tmpH = Height;
854     for (i = 0; i < object->baseTexture.levels; i++)
855     {
856         /* use the callback to create the texture surface */
857         hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &object->surfaces[i],NULL);
858         if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
859             FIXME("Failed to create surface  %p\n", object);
860             /* clean up */
861             object->surfaces[i] = NULL;
862             IWineD3DTexture_Release((IWineD3DTexture *)object);
863
864             *ppTexture = NULL;
865             return hr;
866         }
867
868         IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
869         TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
870         /* calculate the next mipmap level */
871         tmpW = max(1, tmpW >> 1);
872         tmpH = max(1, tmpH >> 1);
873     }
874
875     TRACE("(%p) : Created  texture %p\n", This, object);
876     return WINED3D_OK;
877 }
878
879 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
880                                                       UINT Width, UINT Height, UINT Depth,
881                                                       UINT Levels, DWORD Usage,
882                                                       WINED3DFORMAT Format, WINED3DPOOL Pool,
883                                                       IWineD3DVolumeTexture **ppVolumeTexture,
884                                                       HANDLE *pSharedHandle, IUnknown *parent,
885                                                       D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
886
887     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
888     IWineD3DVolumeTextureImpl *object;
889     unsigned int               i;
890     UINT                       tmpW;
891     UINT                       tmpH;
892     UINT                       tmpD;
893
894     /* TODO: It should only be possible to create textures for formats 
895              that are reported as supported */
896     if (WINED3DFMT_UNKNOWN >= Format) {
897         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
898         return WINED3DERR_INVALIDCALL;
899     }
900
901     D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
902     D3DINITIALIZEBASETEXTURE(object->baseTexture);
903
904     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
905           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
906
907     object->width  = Width;
908     object->height = Height;
909     object->depth  = Depth;
910
911     /* Calculate levels for mip mapping */
912     if (Levels == 0) {
913         object->baseTexture.levels++;
914         tmpW = Width;
915         tmpH = Height;
916         tmpD = Depth;
917         while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
918             tmpW = max(1, tmpW >> 1);
919             tmpH = max(1, tmpH >> 1);
920             tmpD = max(1, tmpD >> 1);
921             object->baseTexture.levels++;
922         }
923         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
924     }
925
926     /* Generate all the surfaces */
927     tmpW = Width;
928     tmpH = Height;
929     tmpD = Depth;
930
931     for (i = 0; i < object->baseTexture.levels; i++)
932     {
933         HRESULT hr;
934         /* Create the volume */
935         hr = D3DCB_CreateVolume(This->parent, parent, tmpW, tmpH, tmpD, Format, Pool, Usage,
936                                 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
937
938         if(FAILED(hr)) {
939             ERR("Creating a volume for the volume texture failed(%08x)\n", hr);
940             IWineD3DVolumeTexture_Release((IWineD3DVolumeTexture *) object);
941             *ppVolumeTexture = NULL;
942             return hr;
943         }
944
945         /* Set its container to this object */
946         IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
947
948         /* calcualte the next mipmap level */
949         tmpW = max(1, tmpW >> 1);
950         tmpH = max(1, tmpH >> 1);
951         tmpD = max(1, tmpD >> 1);
952     }
953
954     *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
955     TRACE("(%p) : Created volume texture %p\n", This, object);
956     return WINED3D_OK;
957 }
958
959 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
960                                                UINT Width, UINT Height, UINT Depth,
961                                                DWORD Usage,
962                                                WINED3DFORMAT Format, WINED3DPOOL Pool,
963                                                IWineD3DVolume** ppVolume,
964                                                HANDLE* pSharedHandle, IUnknown *parent) {
965
966     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
967     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
968     const PixelFormatDesc *formatDesc  = getFormatDescEntry(Format);
969
970     D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
971
972     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
973           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
974
975     object->currentDesc.Width   = Width;
976     object->currentDesc.Height  = Height;
977     object->currentDesc.Depth   = Depth;
978     object->bytesPerPixel       = formatDesc->bpp;
979
980     /** Note: Volume textures cannot be dxtn, hence no need to check here **/
981     object->lockable            = TRUE;
982     object->locked              = FALSE;
983     memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
984     object->dirty               = TRUE;
985
986     return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
987 }
988
989 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
990                                                     UINT Levels, DWORD Usage,
991                                                     WINED3DFORMAT Format, WINED3DPOOL Pool,
992                                                     IWineD3DCubeTexture **ppCubeTexture,
993                                                     HANDLE *pSharedHandle, IUnknown *parent,
994                                                     D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
995
996     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
997     IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
998     unsigned int             i, j;
999     UINT                     tmpW;
1000     HRESULT                  hr;
1001     unsigned int pow2EdgeLength  = EdgeLength;
1002
1003     /* TODO: It should only be possible to create textures for formats 
1004              that are reported as supported */
1005     if (WINED3DFMT_UNKNOWN >= Format) {
1006         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1007         return WINED3DERR_INVALIDCALL;
1008     }
1009
1010     if (!GL_SUPPORT(ARB_TEXTURE_CUBE_MAP) && Pool != WINED3DPOOL_SCRATCH) {
1011         WARN("(%p) : Tried to create not supported cube texture\n", This);
1012         return WINED3DERR_INVALIDCALL;
1013     }
1014
1015     D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1016     D3DINITIALIZEBASETEXTURE(object->baseTexture);
1017
1018     TRACE("(%p) Create Cube Texture\n", This);
1019
1020     /** Non-power2 support **/
1021
1022     /* Find the nearest pow2 match */
1023     pow2EdgeLength = 1;
1024     while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1025
1026     object->edgeLength           = EdgeLength;
1027     /* TODO: support for native non-power 2 */
1028     /* Precalculated scaling for 'faked' non power of two texture coords */
1029     object->pow2scalingFactor    = ((float)EdgeLength) / ((float)pow2EdgeLength);
1030
1031     /* Calculate levels for mip mapping */
1032     if (Levels == 0) {
1033         object->baseTexture.levels++;
1034         tmpW = EdgeLength;
1035         while (tmpW > 1) {
1036             tmpW = max(1, tmpW >> 1);
1037             object->baseTexture.levels++;
1038         }
1039         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1040     }
1041
1042     /* Generate all the surfaces */
1043     tmpW = EdgeLength;
1044     for (i = 0; i < object->baseTexture.levels; i++) {
1045
1046         /* Create the 6 faces */
1047         for (j = 0; j < 6; j++) {
1048
1049             hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool,
1050                                    i /* Level */, j, &object->surfaces[j][i],pSharedHandle);
1051
1052             if(hr!= WINED3D_OK) {
1053                 /* clean up */
1054                 int k;
1055                 int l;
1056                 for (l = 0; l < j; l++) {
1057                     IWineD3DSurface_Release(object->surfaces[j][i]);
1058                 }
1059                 for (k = 0; k < i; k++) {
1060                     for (l = 0; l < 6; l++) {
1061                     IWineD3DSurface_Release(object->surfaces[l][j]);
1062                     }
1063                 }
1064
1065                 FIXME("(%p) Failed to create surface\n",object);
1066                 HeapFree(GetProcessHeap(),0,object);
1067                 *ppCubeTexture = NULL;
1068                 return hr;
1069             }
1070             IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1071             TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1072         }
1073         tmpW = max(1, tmpW >> 1);
1074     }
1075
1076     TRACE("(%p) : Created Cube Texture %p\n", This, object);
1077     *ppCubeTexture = (IWineD3DCubeTexture *) object;
1078     return WINED3D_OK;
1079 }
1080
1081 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1082     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1083     IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1084     HRESULT hr = WINED3DERR_NOTAVAILABLE;
1085
1086     /* Just a check to see if we support this type of query */
1087     switch(Type) {
1088     case WINED3DQUERYTYPE_OCCLUSION:
1089         TRACE("(%p) occlusion query\n", This);
1090         if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1091             hr = WINED3D_OK;
1092         else
1093             WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1094         break;
1095
1096     case WINED3DQUERYTYPE_EVENT:
1097         if(!(GL_SUPPORT(NV_FENCE) || GL_SUPPORT(APPLE_FENCE) )) {
1098             /* Half-Life 2 needs this query. It does not render the main menu correctly otherwise
1099              * Pretend to support it, faking this query does not do much harm except potentially lowering performance
1100              */
1101             FIXME("(%p) Event query: Unimplemented, but pretending to be supported\n", This);
1102         }
1103         hr = WINED3D_OK;
1104         break;
1105
1106     case WINED3DQUERYTYPE_VCACHE:
1107     case WINED3DQUERYTYPE_RESOURCEMANAGER:
1108     case WINED3DQUERYTYPE_VERTEXSTATS:
1109     case WINED3DQUERYTYPE_TIMESTAMP:
1110     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1111     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1112     case WINED3DQUERYTYPE_PIPELINETIMINGS:
1113     case WINED3DQUERYTYPE_INTERFACETIMINGS:
1114     case WINED3DQUERYTYPE_VERTEXTIMINGS:
1115     case WINED3DQUERYTYPE_PIXELTIMINGS:
1116     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1117     case WINED3DQUERYTYPE_CACHEUTILIZATION:
1118     default:
1119         FIXME("(%p) Unhandled query type %d\n", This, Type);
1120     }
1121     if(NULL == ppQuery || hr != WINED3D_OK) {
1122         return hr;
1123     }
1124
1125     D3DCREATEOBJECTINSTANCE(object, Query)
1126     object->type         = Type;
1127     /* allocated the 'extended' data based on the type of query requested */
1128     switch(Type){
1129     case WINED3DQUERYTYPE_OCCLUSION:
1130         if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1131             TRACE("(%p) Allocating data for an occlusion query\n", This);
1132             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1133             GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1134             break;
1135         }
1136     case WINED3DQUERYTYPE_EVENT:
1137         /* TODO: GL_APPLE_fence */
1138         if(GL_SUPPORT(APPLE_FENCE)) {
1139             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryEventData));
1140             GL_EXTCALL(glGenFencesAPPLE(1, &((WineQueryEventData *)(object->extendedData))->fenceId));
1141             checkGLcall("glGenFencesAPPLE");
1142         } else if(GL_SUPPORT(NV_FENCE)) {
1143             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryEventData));
1144             GL_EXTCALL(glGenFencesNV(1, &((WineQueryEventData *)(object->extendedData))->fenceId));
1145             checkGLcall("glGenFencesNV");
1146         }
1147         break;
1148
1149     case WINED3DQUERYTYPE_VCACHE:
1150     case WINED3DQUERYTYPE_RESOURCEMANAGER:
1151     case WINED3DQUERYTYPE_VERTEXSTATS:
1152     case WINED3DQUERYTYPE_TIMESTAMP:
1153     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1154     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1155     case WINED3DQUERYTYPE_PIPELINETIMINGS:
1156     case WINED3DQUERYTYPE_INTERFACETIMINGS:
1157     case WINED3DQUERYTYPE_VERTEXTIMINGS:
1158     case WINED3DQUERYTYPE_PIXELTIMINGS:
1159     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1160     case WINED3DQUERYTYPE_CACHEUTILIZATION:
1161     default:
1162         object->extendedData = 0;
1163         FIXME("(%p) Unhandled query type %d\n",This , Type);
1164     }
1165     TRACE("(%p) : Created Query %p\n", This, object);
1166     return WINED3D_OK;
1167 }
1168
1169 /*****************************************************************************
1170  * IWineD3DDeviceImpl_SetupFullscreenWindow
1171  *
1172  * Helper function that modifies a HWND's Style and ExStyle for proper
1173  * fullscreen use.
1174  *
1175  * Params:
1176  *  iface: Pointer to the IWineD3DDevice interface
1177  *  window: Window to setup
1178  *
1179  *****************************************************************************/
1180 static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *iface, HWND window) {
1181     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1182
1183     LONG style, exStyle;
1184     /* Don't do anything if an original style is stored.
1185      * That shouldn't happen
1186      */
1187     TRACE("(%p): Setting up window %p for exclusive mode\n", This, window);
1188     if (This->style || This->exStyle) {
1189         ERR("(%p): Want to change the window parameters of HWND %p, but "
1190             "another style is stored for restoration afterwards\n", This, window);
1191     }
1192
1193     /* Get the parameters and save them */
1194     style = GetWindowLongW(window, GWL_STYLE);
1195     exStyle = GetWindowLongW(window, GWL_EXSTYLE);
1196     This->style = style;
1197     This->exStyle = exStyle;
1198
1199     /* Filter out window decorations */
1200     style &= ~WS_CAPTION;
1201     style &= ~WS_THICKFRAME;
1202     exStyle &= ~WS_EX_WINDOWEDGE;
1203     exStyle &= ~WS_EX_CLIENTEDGE;
1204
1205     /* Make sure the window is managed, otherwise we won't get keyboard input */
1206     style |= WS_POPUP | WS_SYSMENU;
1207
1208     TRACE("Old style was %08x,%08x, setting to %08x,%08x\n",
1209           This->style, This->exStyle, style, exStyle);
1210
1211     SetWindowLongW(window, GWL_STYLE, style);
1212     SetWindowLongW(window, GWL_EXSTYLE, exStyle);
1213
1214     /* Inform the window about the update. */
1215     SetWindowPos(window, HWND_TOP, 0, 0,
1216             This->ddraw_width, This->ddraw_height, SWP_FRAMECHANGED);
1217     ShowWindow(window, SW_NORMAL);
1218 }
1219
1220 /*****************************************************************************
1221  * IWineD3DDeviceImpl_RestoreWindow
1222  *
1223  * Helper function that restores a windows' properties when taking it out
1224  * of fullscreen mode
1225  *
1226  * Params:
1227  *  iface: Pointer to the IWineD3DDevice interface
1228  *  window: Window to setup
1229  *
1230  *****************************************************************************/
1231 static void WINAPI IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND window) {
1232     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1233
1234     /* This could be a DDSCL_NORMAL -> DDSCL_NORMAL
1235      * switch, do nothing
1236      */
1237     if (!This->style && !This->exStyle) return;
1238
1239     TRACE("(%p): Restoring window settings of window %p to %08x, %08x\n",
1240           This, window, This->style, This->exStyle);
1241
1242     SetWindowLongW(window, GWL_STYLE, This->style);
1243     SetWindowLongW(window, GWL_EXSTYLE, This->exStyle);
1244
1245     /* Delete the old values */
1246     This->style = 0;
1247     This->exStyle = 0;
1248
1249     /* Inform the window about the update */
1250     SetWindowPos(window, 0 /* InsertAfter, ignored */,
1251                  0, 0, 0, 0, /* Pos, Size, ignored */
1252                  SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
1253 }
1254
1255 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1256 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS*  pPresentationParameters,                                                                   IWineD3DSwapChain** ppSwapChain,
1257                                                             IUnknown* parent,
1258                                                             D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1259                                                             D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1260     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1261
1262     HDC                     hDc;
1263     IWineD3DSwapChainImpl  *object; /** NOTE: impl ref allowed since this is a create function **/
1264     HRESULT                 hr = WINED3D_OK;
1265     IUnknown               *bufferParent;
1266     Display                *display;
1267
1268     TRACE("(%p) : Created Aditional Swap Chain\n", This);
1269
1270    /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1271    * does a device hold a reference to a swap chain giving them a lifetime of the device
1272    * or does the swap chain notify the device of its destruction.
1273     *******************************/
1274
1275     /* Check the params */
1276     if(pPresentationParameters->BackBufferCount > WINED3DPRESENT_BACK_BUFFER_MAX) {
1277         ERR("App requested %d back buffers, this is not supported for now\n", pPresentationParameters->BackBufferCount);
1278         return WINED3DERR_INVALIDCALL;
1279     } else if (pPresentationParameters->BackBufferCount > 1) {
1280         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");
1281     }
1282
1283     D3DCREATEOBJECTINSTANCE(object, SwapChain)
1284
1285     /*********************
1286     * Lookup the window Handle and the relating X window handle
1287     ********************/
1288
1289     /* Setup hwnd we are using, plus which display this equates to */
1290     object->win_handle = pPresentationParameters->hDeviceWindow;
1291     if (!object->win_handle) {
1292         object->win_handle = This->createParms.hFocusWindow;
1293     }
1294
1295     object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1296     if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1297         ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1298         return WINED3DERR_NOTAVAILABLE;
1299     }
1300     hDc                = GetDC(object->win_handle);
1301     display            = get_display(hDc);
1302     ReleaseDC(object->win_handle, hDc);
1303     TRACE("Using a display of %p %p\n", display, hDc);
1304
1305     if (NULL == display || NULL == hDc) {
1306         WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1307         return WINED3DERR_NOTAVAILABLE;
1308     }
1309
1310     if (object->win == 0) {
1311         WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1312         return WINED3DERR_NOTAVAILABLE;
1313     }
1314
1315     object->orig_width = GetSystemMetrics(SM_CXSCREEN);
1316     object->orig_height = GetSystemMetrics(SM_CYSCREEN);
1317     object->orig_fmt = pixelformat_for_depth(GetDeviceCaps(hDc, BITSPIXEL) * GetDeviceCaps(hDc, PLANES));
1318
1319     /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1320      *  then the corresponding dimension of the client area of the hDeviceWindow
1321      *  (or the focus window, if hDeviceWindow is NULL) is taken.
1322       **********************/
1323
1324     if (pPresentationParameters->Windowed &&
1325         ((pPresentationParameters->BackBufferWidth == 0) ||
1326          (pPresentationParameters->BackBufferHeight == 0))) {
1327
1328         RECT Rect;
1329         GetClientRect(object->win_handle, &Rect);
1330
1331         if (pPresentationParameters->BackBufferWidth == 0) {
1332            pPresentationParameters->BackBufferWidth = Rect.right;
1333            TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
1334         }
1335         if (pPresentationParameters->BackBufferHeight == 0) {
1336            pPresentationParameters->BackBufferHeight = Rect.bottom;
1337            TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
1338         }
1339     }
1340
1341     /* Put the correct figures in the presentation parameters */
1342     TRACE("Copying across presentation parameters\n");
1343     object->presentParms = *pPresentationParameters;
1344
1345     TRACE("calling rendertarget CB\n");
1346     hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1347                              parent,
1348                              object->presentParms.BackBufferWidth,
1349                              object->presentParms.BackBufferHeight,
1350                              object->presentParms.BackBufferFormat,
1351                              object->presentParms.MultiSampleType,
1352                              object->presentParms.MultiSampleQuality,
1353                              TRUE /* Lockable */,
1354                              &object->frontBuffer,
1355                              NULL /* pShared (always null)*/);
1356     if (object->frontBuffer != NULL) {
1357         IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1358     } else {
1359         ERR("Failed to create the front buffer\n");
1360         goto error;
1361     }
1362
1363     /**
1364     * Create an opengl context for the display visual
1365     *  NOTE: the visual is chosen as the window is created and the glcontext cannot
1366     *     use different properties after that point in time. FIXME: How to handle when requested format
1367     *     doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1368     *     it chooses is identical to the one already being used!
1369      **********************************/
1370     /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1371
1372     object->context = HeapAlloc(GetProcessHeap(), 0, sizeof(object->context));
1373     if(!object->context)
1374         return E_OUTOFMEMORY;
1375     object->num_contexts = 1;
1376
1377     ENTER_GL();
1378     object->context[0] = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, display, object->win);
1379     LEAVE_GL();
1380
1381     if (!object->context[0]) {
1382         ERR("Failed to create a new context\n");
1383         hr = WINED3DERR_NOTAVAILABLE;
1384         goto error;
1385     } else {
1386         TRACE("Context created (HWND=%p, glContext=%p, Window=%ld)\n",
1387                object->win_handle, object->context[0]->glCtx, object->win);
1388     }
1389
1390    /*********************
1391    * Windowed / Fullscreen
1392    *******************/
1393
1394    /**
1395    * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1396    * so we should really check to see if there is a fullscreen swapchain already
1397    * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1398     **************************************/
1399
1400    if (!pPresentationParameters->Windowed) {
1401
1402         DEVMODEW devmode;
1403         HDC      hdc;
1404         int      bpp = 0;
1405         RECT     clip_rc;
1406
1407         /* Get info on the current display setup */
1408         hdc = GetDC(0);
1409         bpp = GetDeviceCaps(hdc, BITSPIXEL);
1410         ReleaseDC(0, hdc);
1411
1412         /* Change the display settings */
1413         memset(&devmode, 0, sizeof(DEVMODEW));
1414         devmode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1415         devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1416         devmode.dmPelsWidth  = pPresentationParameters->BackBufferWidth;
1417         devmode.dmPelsHeight = pPresentationParameters->BackBufferHeight;
1418         MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1419         ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1420
1421         /* For GetDisplayMode */
1422         This->ddraw_width = devmode.dmPelsWidth;
1423         This->ddraw_height = devmode.dmPelsHeight;
1424         This->ddraw_format = pPresentationParameters->BackBufferFormat;
1425
1426         IWineD3DDevice_SetFullscreen(iface, TRUE);
1427
1428         /* And finally clip mouse to our screen */
1429         SetRect(&clip_rc, 0, 0, devmode.dmPelsWidth, devmode.dmPelsHeight);
1430         ClipCursor(&clip_rc);
1431     }
1432
1433    /*********************
1434    * Create the back, front and stencil buffers
1435    *******************/
1436     if(object->presentParms.BackBufferCount > 0) {
1437         int i;
1438
1439         object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1440         if(!object->backBuffer) {
1441             ERR("Out of memory\n");
1442             hr = E_OUTOFMEMORY;
1443             goto error;
1444         }
1445
1446         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1447             TRACE("calling rendertarget CB\n");
1448             hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1449                                     parent,
1450                                     object->presentParms.BackBufferWidth,
1451                                     object->presentParms.BackBufferHeight,
1452                                     object->presentParms.BackBufferFormat,
1453                                     object->presentParms.MultiSampleType,
1454                                     object->presentParms.MultiSampleQuality,
1455                                     TRUE /* Lockable */,
1456                                     &object->backBuffer[i],
1457                                     NULL /* pShared (always null)*/);
1458             if(hr == WINED3D_OK && object->backBuffer[i]) {
1459                 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1460             } else {
1461                 ERR("Cannot create new back buffer\n");
1462                 goto error;
1463             }
1464             ENTER_GL();
1465             glDrawBuffer(GL_BACK);
1466             checkGLcall("glDrawBuffer(GL_BACK)");
1467             LEAVE_GL();
1468         }
1469     } else {
1470         object->backBuffer = NULL;
1471
1472         /* Single buffering - draw to front buffer */
1473         ENTER_GL();
1474         glDrawBuffer(GL_FRONT);
1475         checkGLcall("glDrawBuffer(GL_FRONT)");
1476         LEAVE_GL();
1477     }
1478
1479     /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1480     if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK) {
1481         TRACE("Creating depth stencil buffer\n");
1482         if (This->depthStencilBuffer == NULL ) {
1483             hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1484                                     parent,
1485                                     object->presentParms.BackBufferWidth,
1486                                     object->presentParms.BackBufferHeight,
1487                                     object->presentParms.AutoDepthStencilFormat,
1488                                     object->presentParms.MultiSampleType,
1489                                     object->presentParms.MultiSampleQuality,
1490                                     FALSE /* FIXME: Discard */,
1491                                     &This->depthStencilBuffer,
1492                                     NULL /* pShared (always null)*/  );
1493             if (This->depthStencilBuffer != NULL)
1494                 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1495         }
1496
1497         /** TODO: A check on width, height and multisample types
1498         *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1499          ****************************/
1500         object->wantsDepthStencilBuffer = TRUE;
1501     } else {
1502         object->wantsDepthStencilBuffer = FALSE;
1503     }
1504
1505     TRACE("Created swapchain %p\n", object);
1506     TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1507     return WINED3D_OK;
1508
1509 error:
1510     if (object->backBuffer) {
1511         int i;
1512         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1513             if(object->backBuffer[i]) {
1514                 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1515                 IUnknown_Release(bufferParent); /* once for the get parent */
1516                 if (IUnknown_Release(bufferParent) > 0) {
1517                     FIXME("(%p) Something's still holding the back buffer\n",This);
1518                 }
1519             }
1520         }
1521         HeapFree(GetProcessHeap(), 0, object->backBuffer);
1522         object->backBuffer = NULL;
1523     }
1524     if(object->context[0])
1525         DestroyContext(This, object->context[0]);
1526     if(object->frontBuffer) {
1527         IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1528         IUnknown_Release(bufferParent); /* once for the get parent */
1529         if (IUnknown_Release(bufferParent) > 0) {
1530             FIXME("(%p) Something's still holding the front buffer\n",This);
1531         }
1532     }
1533     HeapFree(GetProcessHeap(), 0, object);
1534     return hr;
1535 }
1536
1537 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1538 static UINT     WINAPI  IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1539     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1540     TRACE("(%p)\n", This);
1541
1542     return This->NumberOfSwapChains;
1543 }
1544
1545 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1546     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1547     TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1548
1549     if(iSwapChain < This->NumberOfSwapChains) {
1550         *pSwapChain = This->swapchains[iSwapChain];
1551         IWineD3DSwapChain_AddRef(*pSwapChain);
1552         TRACE("(%p) returning %p\n", This, *pSwapChain);
1553         return WINED3D_OK;
1554     } else {
1555         TRACE("Swapchain out of range\n");
1556         *pSwapChain = NULL;
1557         return WINED3DERR_INVALIDCALL;
1558     }
1559 }
1560
1561 /*****
1562  * Vertex Declaration
1563  *****/
1564 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration,
1565         IUnknown *parent, const WINED3DVERTEXELEMENT *elements, size_t element_count) {
1566     IWineD3DDeviceImpl            *This   = (IWineD3DDeviceImpl *)iface;
1567     IWineD3DVertexDeclarationImpl *object = NULL;
1568     HRESULT hr = WINED3D_OK;
1569
1570     TRACE("(%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p\n",
1571             This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, elements, element_count, ppVertexDeclaration);
1572
1573     D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1574
1575     hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, elements, element_count);
1576
1577     return hr;
1578 }
1579
1580 static size_t ConvertFvfToDeclaration(DWORD fvf, WINED3DVERTEXELEMENT** ppVertexElements) {
1581
1582     unsigned int idx, idx2;
1583     unsigned int offset;
1584     BOOL has_pos = (fvf & WINED3DFVF_POSITION_MASK) != 0;
1585     BOOL has_blend = (fvf & WINED3DFVF_XYZB5) > WINED3DFVF_XYZRHW;
1586     BOOL has_blend_idx = has_blend &&
1587        (((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB5) ||
1588         (fvf & WINED3DFVF_LASTBETA_D3DCOLOR) ||
1589         (fvf & WINED3DFVF_LASTBETA_UBYTE4));
1590     BOOL has_normal = (fvf & WINED3DFVF_NORMAL) != 0;
1591     BOOL has_psize = (fvf & WINED3DFVF_PSIZE) != 0;
1592     BOOL has_diffuse = (fvf & WINED3DFVF_DIFFUSE) != 0;
1593     BOOL has_specular = (fvf & WINED3DFVF_SPECULAR) !=0;
1594
1595     DWORD num_textures = (fvf & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
1596     DWORD texcoords = (fvf & 0x00FF0000) >> 16;
1597
1598     WINED3DVERTEXELEMENT end_element = WINED3DDECL_END();
1599     WINED3DVERTEXELEMENT *elements = NULL;
1600
1601     unsigned int size;
1602     DWORD num_blends = 1 + (((fvf & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1);
1603     if (has_blend_idx) num_blends--;
1604
1605     /* Compute declaration size */
1606     size = has_pos + (has_blend && num_blends > 0) + has_blend_idx + has_normal +
1607            has_psize + has_diffuse + has_specular + num_textures + 1;
1608
1609     /* convert the declaration */
1610     elements = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WINED3DVERTEXELEMENT));
1611     if (!elements)
1612         return 0;
1613
1614     memcpy(&elements[size-1], &end_element, sizeof(WINED3DVERTEXELEMENT));
1615     idx = 0;
1616     if (has_pos) {
1617         if (!has_blend && (fvf & WINED3DFVF_XYZRHW)) {
1618             elements[idx].Type = WINED3DDECLTYPE_FLOAT4;
1619             elements[idx].Usage = WINED3DDECLUSAGE_POSITIONT;
1620         }
1621         else {
1622             elements[idx].Type = WINED3DDECLTYPE_FLOAT3;
1623             elements[idx].Usage = WINED3DDECLUSAGE_POSITION;
1624         }
1625         elements[idx].UsageIndex = 0;
1626         idx++;
1627     }
1628     if (has_blend && (num_blends > 0)) {
1629         if (((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2) && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR))
1630             elements[idx].Type = WINED3DDECLTYPE_D3DCOLOR;
1631         else
1632             elements[idx].Type = WINED3DDECLTYPE_FLOAT1 + num_blends - 1;
1633         elements[idx].Usage = WINED3DDECLUSAGE_BLENDWEIGHT;
1634         elements[idx].UsageIndex = 0;
1635         idx++;
1636     }
1637     if (has_blend_idx) {
1638         if (fvf & WINED3DFVF_LASTBETA_UBYTE4 ||
1639             (((fvf & WINED3DFVF_XYZB5) == WINED3DFVF_XYZB2) && (fvf & WINED3DFVF_LASTBETA_D3DCOLOR)))
1640             elements[idx].Type = WINED3DDECLTYPE_UBYTE4;
1641         else if (fvf & WINED3DFVF_LASTBETA_D3DCOLOR)
1642             elements[idx].Type = WINED3DDECLTYPE_D3DCOLOR;
1643         else
1644             elements[idx].Type = WINED3DDECLTYPE_FLOAT1;
1645         elements[idx].Usage = WINED3DDECLUSAGE_BLENDINDICES;
1646         elements[idx].UsageIndex = 0;
1647         idx++;
1648     }
1649     if (has_normal) {
1650         elements[idx].Type = WINED3DDECLTYPE_FLOAT3;
1651         elements[idx].Usage = WINED3DDECLUSAGE_NORMAL;
1652         elements[idx].UsageIndex = 0;
1653         idx++;
1654     }
1655     if (has_psize) {
1656         elements[idx].Type = WINED3DDECLTYPE_FLOAT1;
1657         elements[idx].Usage = WINED3DDECLUSAGE_PSIZE;
1658         elements[idx].UsageIndex = 0;
1659         idx++;
1660     }
1661     if (has_diffuse) {
1662         elements[idx].Type = WINED3DDECLTYPE_D3DCOLOR;
1663         elements[idx].Usage = WINED3DDECLUSAGE_COLOR;
1664         elements[idx].UsageIndex = 0;
1665         idx++;
1666     }
1667     if (has_specular) {
1668         elements[idx].Type = WINED3DDECLTYPE_D3DCOLOR;
1669         elements[idx].Usage = WINED3DDECLUSAGE_COLOR;
1670         elements[idx].UsageIndex = 1;
1671         idx++;
1672     }
1673     for (idx2 = 0; idx2 < num_textures; idx2++) {
1674         unsigned int numcoords = (texcoords >> (idx2*2)) & 0x03;
1675         switch (numcoords) {
1676             case WINED3DFVF_TEXTUREFORMAT1:
1677                 elements[idx].Type = WINED3DDECLTYPE_FLOAT1;
1678                 break;
1679             case WINED3DFVF_TEXTUREFORMAT2:
1680                 elements[idx].Type = WINED3DDECLTYPE_FLOAT2;
1681                 break;
1682             case WINED3DFVF_TEXTUREFORMAT3:
1683                 elements[idx].Type = WINED3DDECLTYPE_FLOAT3;
1684                 break;
1685             case WINED3DFVF_TEXTUREFORMAT4:
1686                 elements[idx].Type = WINED3DDECLTYPE_FLOAT4;
1687                 break;
1688         }
1689         elements[idx].Usage = WINED3DDECLUSAGE_TEXCOORD;
1690         elements[idx].UsageIndex = idx2;
1691         idx++;
1692     }
1693
1694     /* Now compute offsets, and initialize the rest of the fields */
1695     for (idx = 0, offset = 0; idx < size-1; idx++) {
1696         elements[idx].Stream = 0;
1697         elements[idx].Method = WINED3DDECLMETHOD_DEFAULT;
1698         elements[idx].Offset = offset;
1699         offset += WINED3D_ATR_SIZE(elements[idx].Type) * WINED3D_ATR_TYPESIZE(elements[idx].Type);
1700     }
1701
1702     *ppVertexElements = elements;
1703     return size;
1704 }
1705
1706 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *Parent, DWORD Fvf) {
1707     WINED3DVERTEXELEMENT* elements = NULL;
1708     size_t size;
1709     DWORD hr;
1710
1711     size = ConvertFvfToDeclaration(Fvf, &elements);
1712     if (size == 0) return WINED3DERR_OUTOFVIDEOMEMORY;
1713
1714     hr = IWineD3DDevice_CreateVertexDeclaration(iface, ppVertexDeclaration, Parent, elements, size);
1715     HeapFree(GetProcessHeap(), 0, elements);
1716     if (hr != S_OK) return hr;
1717
1718     return WINED3D_OK;
1719 }
1720
1721 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1722 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, IWineD3DVertexDeclaration *vertex_declaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1723     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1724     IWineD3DVertexShaderImpl *object;  /* NOTE: impl usage is ok, this is a create */
1725     HRESULT hr = WINED3D_OK;
1726     D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1727     object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1728
1729     TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1730
1731     if (vertex_declaration) {
1732         IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration);
1733     }
1734
1735     hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1736
1737     if (WINED3D_OK != hr) {
1738         FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1739         IWineD3DVertexShader_Release(*ppVertexShader);
1740         return WINED3DERR_INVALIDCALL;
1741     }
1742
1743     return WINED3D_OK;
1744 }
1745
1746 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1747     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1748     IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1749     HRESULT hr = WINED3D_OK;
1750
1751     D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
1752     object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1753     hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1754     if (WINED3D_OK == hr) {
1755         TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1756     } else {
1757         WARN("(%p) : Failed to create pixel shader\n", This);
1758     }
1759
1760     return hr;
1761 }
1762
1763 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1764     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1765     IWineD3DPaletteImpl *object;
1766     HRESULT hr;
1767     TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1768
1769     /* Create the new object */
1770     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1771     if(!object) {
1772         ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1773         return E_OUTOFMEMORY;
1774     }
1775
1776     object->lpVtbl = &IWineD3DPalette_Vtbl;
1777     object->ref = 1;
1778     object->Flags = Flags;
1779     object->parent = Parent;
1780     object->wineD3DDevice = This;
1781     object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1782         
1783     object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1784
1785     if(!object->hpal) {
1786         HeapFree( GetProcessHeap(), 0, object);
1787         return E_OUTOFMEMORY;
1788     }
1789
1790     hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1791     if(FAILED(hr)) {
1792         IWineD3DPalette_Release((IWineD3DPalette *) object);
1793         return hr;
1794     }
1795
1796     *Palette = (IWineD3DPalette *) object;
1797
1798     return WINED3D_OK;
1799 }
1800
1801 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1802     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1803     IWineD3DSwapChainImpl *swapchain;
1804     HRESULT hr;
1805     DWORD state;
1806
1807     TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1808     if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1809
1810     /* TODO: Test if OpenGL is compiled in and loaded */
1811
1812     /* Initialize the texture unit mapping to a 1:1 mapping */
1813     for(state = 0; state < MAX_SAMPLERS; state++) {
1814         This->texUnitMap[state] = state;
1815     }
1816     This->oneToOneTexUnitMap = TRUE;
1817
1818     /* Setup the implicit swapchain */
1819     TRACE("Creating implicit swapchain\n");
1820     hr=D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
1821     if (FAILED(hr) || !swapchain) {
1822         WARN("Failed to create implicit swapchain\n");
1823         return hr;
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 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     return WINED3D_OK;
3309 }
3310
3311 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3312     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3313
3314     if (NULL == ppShader) {
3315         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3316         return WINED3DERR_INVALIDCALL;
3317     }
3318
3319     *ppShader =  This->stateBlock->pixelShader;
3320     if (NULL != *ppShader) {
3321         IWineD3DPixelShader_AddRef(*ppShader);
3322     }
3323     TRACE("(%p) : returning %p\n", This, *ppShader);
3324     return WINED3D_OK;
3325 }
3326
3327 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3328     IWineD3DDevice *iface,
3329     UINT start,
3330     CONST BOOL *srcData,
3331     UINT count) {
3332
3333     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3334     int i, cnt = min(count, MAX_CONST_B - start);
3335
3336     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3337             iface, srcData, start, count);
3338
3339     if (srcData == NULL || cnt < 0)
3340         return WINED3DERR_INVALIDCALL;
3341
3342     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3343     for (i = 0; i < cnt; i++)
3344         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3345
3346     for (i = start; i < cnt + start; ++i) {
3347         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3348         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
3349     }
3350
3351     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3352
3353     return WINED3D_OK;
3354 }
3355
3356 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3357     IWineD3DDevice *iface,
3358     UINT start,
3359     BOOL *dstData,
3360     UINT count) {
3361
3362     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3363     int cnt = min(count, MAX_CONST_B - start);
3364
3365     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3366             iface, dstData, start, count);
3367
3368     if (dstData == NULL || cnt < 0)
3369         return WINED3DERR_INVALIDCALL;
3370
3371     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3372     return WINED3D_OK;
3373 }
3374
3375 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3376     IWineD3DDevice *iface,
3377     UINT start,
3378     CONST int *srcData,
3379     UINT count) {
3380
3381     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3382     int i, cnt = min(count, MAX_CONST_I - start);
3383
3384     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3385             iface, srcData, start, count);
3386
3387     if (srcData == NULL || cnt < 0)
3388         return WINED3DERR_INVALIDCALL;
3389
3390     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3391     for (i = 0; i < cnt; i++)
3392         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3393            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3394
3395     for (i = start; i < cnt + start; ++i) {
3396         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3397         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
3398     }
3399
3400     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3401
3402     return WINED3D_OK;
3403 }
3404
3405 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3406     IWineD3DDevice *iface,
3407     UINT start,
3408     int *dstData,
3409     UINT count) {
3410
3411     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3412     int cnt = min(count, MAX_CONST_I - start);
3413
3414     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3415             iface, dstData, start, count);
3416
3417     if (dstData == NULL || cnt < 0)
3418         return WINED3DERR_INVALIDCALL;
3419
3420     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3421     return WINED3D_OK;
3422 }
3423
3424 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3425     IWineD3DDevice *iface,
3426     UINT start,
3427     CONST float *srcData,
3428     UINT count) {
3429
3430     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3431     int i;
3432
3433     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3434             iface, srcData, start, count);
3435
3436     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3437     if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
3438         return WINED3DERR_INVALIDCALL;
3439
3440     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3441     if(TRACE_ON(d3d)) {
3442         for (i = 0; i < count; i++)
3443             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3444                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3445     }
3446
3447     for (i = start; i < count + start; ++i) {
3448         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3449             constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry);
3450             if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
3451                 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
3452                 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3453             }
3454             ptr->idx[ptr->count++] = i;
3455             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3456         }
3457         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3458     }
3459
3460     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3461
3462     return WINED3D_OK;
3463 }
3464
3465 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3466     IWineD3DDevice *iface,
3467     UINT start,
3468     float *dstData,
3469     UINT count) {
3470
3471     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3472     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3473
3474     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3475             iface, dstData, start, count);
3476
3477     if (dstData == NULL || cnt < 0)
3478         return WINED3DERR_INVALIDCALL;
3479
3480     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3481     return WINED3D_OK;
3482 }
3483
3484 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3485 static HRESULT
3486 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3487     char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
3488     unsigned int i;
3489     DWORD DestFVF = dest->fvf;
3490     WINED3DVIEWPORT vp;
3491     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3492     BOOL doClip;
3493     int numTextures;
3494
3495     if (lpStrideData->u.s.normal.lpData) {
3496         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3497     }
3498
3499     if (lpStrideData->u.s.position.lpData == NULL) {
3500         ERR("Source has no position mask\n");
3501         return WINED3DERR_INVALIDCALL;
3502     }
3503
3504     /* We might access VBOs from this code, so hold the lock */
3505     ENTER_GL();
3506
3507     if (dest->resource.allocatedMemory == NULL) {
3508         /* This may happen if we do direct locking into a vbo. Unlikely,
3509          * but theoretically possible(ddraw processvertices test)
3510          */
3511         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3512         if(!dest->resource.allocatedMemory) {
3513             LEAVE_GL();
3514             ERR("Out of memory\n");
3515             return E_OUTOFMEMORY;
3516         }
3517         if(dest->vbo) {
3518             void *src;
3519             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3520             checkGLcall("glBindBufferARB");
3521             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3522             if(src) {
3523                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3524             }
3525             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3526             checkGLcall("glUnmapBufferARB");
3527         }
3528     }
3529
3530     /* Get a pointer into the destination vbo(create one if none exists) and
3531      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3532      */
3533     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3534         CreateVBO(dest);
3535     }
3536
3537     if(dest->vbo) {
3538         unsigned char extrabytes = 0;
3539         /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
3540          * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
3541          * this may write 4 extra bytes beyond the area that should be written
3542          */
3543         if(DestFVF == WINED3DFVF_XYZ) extrabytes = 4;
3544         dest_conv_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * get_flexible_vertex_size(DestFVF) + extrabytes);
3545         if(!dest_conv_addr) {
3546             ERR("Out of memory\n");
3547             /* Continue without storing converted vertices */
3548         }
3549         dest_conv = dest_conv_addr;
3550     }
3551
3552     /* Should I clip?
3553      * a) WINED3DRS_CLIPPING is enabled
3554      * b) WINED3DVOP_CLIP is passed
3555      */
3556     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3557         static BOOL warned = FALSE;
3558         /*
3559          * The clipping code is not quite correct. Some things need
3560          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3561          * so disable clipping for now.
3562          * (The graphics in Half-Life are broken, and my processvertices
3563          *  test crashes with IDirect3DDevice3)
3564         doClip = TRUE;
3565          */
3566         doClip = FALSE;
3567         if(!warned) {
3568            warned = TRUE;
3569            FIXME("Clipping is broken and disabled for now\n");
3570         }
3571     } else doClip = FALSE;
3572     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3573
3574     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3575                                  WINED3DTS_VIEW,
3576                                  &view_mat);
3577     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3578                                  WINED3DTS_PROJECTION,
3579                                  &proj_mat);
3580     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3581                                  WINED3DTS_WORLDMATRIX(0),
3582                                  &world_mat);
3583
3584     TRACE("View mat:\n");
3585     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);
3586     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);
3587     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);
3588     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);
3589
3590     TRACE("Proj mat:\n");
3591     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);
3592     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);
3593     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);
3594     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);
3595
3596     TRACE("World mat:\n");
3597     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);
3598     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);
3599     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);
3600     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);
3601
3602     /* Get the viewport */
3603     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3604     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3605           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3606
3607     multiply_matrix(&mat,&view_mat,&world_mat);
3608     multiply_matrix(&mat,&proj_mat,&mat);
3609
3610     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3611
3612     for (i = 0; i < dwCount; i+= 1) {
3613         unsigned int tex_index;
3614
3615         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3616              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3617             /* The position first */
3618             float *p =
3619               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3620             float x, y, z, rhw;
3621             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3622
3623             /* Multiplication with world, view and projection matrix */
3624             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);
3625             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);
3626             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);
3627             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);
3628
3629             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3630
3631             /* WARNING: The following things are taken from d3d7 and were not yet checked
3632              * against d3d8 or d3d9!
3633              */
3634
3635             /* Clipping conditions: From
3636              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
3637              *
3638              * A vertex is clipped if it does not match the following requirements
3639              * -rhw < x <= rhw
3640              * -rhw < y <= rhw
3641              *    0 < z <= rhw
3642              *    0 < rhw ( Not in d3d7, but tested in d3d7)
3643              *
3644              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3645              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3646              *
3647              */
3648
3649             if( !doClip ||
3650                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3651                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
3652                   ( rhw > eps ) ) ) {
3653
3654                 /* "Normal" viewport transformation (not clipped)
3655                  * 1) The values are divided by rhw
3656                  * 2) The y axis is negative, so multiply it with -1
3657                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3658                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3659                  * 4) Multiply x with Width/2 and add Width/2
3660                  * 5) The same for the height
3661                  * 6) Add the viewpoint X and Y to the 2D coordinates and
3662                  *    The minimum Z value to z
3663                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3664                  *
3665                  * Well, basically it's simply a linear transformation into viewport
3666                  * coordinates
3667                  */
3668
3669                 x /= rhw;
3670                 y /= rhw;
3671                 z /= rhw;
3672
3673                 y *= -1;
3674
3675                 x *= vp.Width / 2;
3676                 y *= vp.Height / 2;
3677                 z *= vp.MaxZ - vp.MinZ;
3678
3679                 x += vp.Width / 2 + vp.X;
3680                 y += vp.Height / 2 + vp.Y;
3681                 z += vp.MinZ;
3682
3683                 rhw = 1 / rhw;
3684             } else {
3685                 /* That vertex got clipped
3686                  * Contrary to OpenGL it is not dropped completely, it just
3687                  * undergoes a different calculation.
3688                  */
3689                 TRACE("Vertex got clipped\n");
3690                 x += rhw;
3691                 y += rhw;
3692
3693                 x  /= 2;
3694                 y  /= 2;
3695
3696                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3697                  * outside of the main vertex buffer memory. That needs some more
3698                  * investigation...
3699                  */
3700             }
3701
3702             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3703
3704
3705             ( (float *) dest_ptr)[0] = x;
3706             ( (float *) dest_ptr)[1] = y;
3707             ( (float *) dest_ptr)[2] = z;
3708             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3709
3710             dest_ptr += 3 * sizeof(float);
3711
3712             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3713                 dest_ptr += sizeof(float);
3714             }
3715
3716             if(dest_conv) {
3717                 float w = 1 / rhw;
3718                 ( (float *) dest_conv)[0] = x * w;
3719                 ( (float *) dest_conv)[1] = y * w;
3720                 ( (float *) dest_conv)[2] = z * w;
3721                 ( (float *) dest_conv)[3] = w;
3722
3723                 dest_conv += 3 * sizeof(float);
3724
3725                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3726                     dest_conv += sizeof(float);
3727                 }
3728             }
3729         }
3730         if (DestFVF & WINED3DFVF_PSIZE) {
3731             dest_ptr += sizeof(DWORD);
3732             if(dest_conv) dest_conv += sizeof(DWORD);
3733         }
3734         if (DestFVF & WINED3DFVF_NORMAL) {
3735             float *normal =
3736               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
3737             /* AFAIK this should go into the lighting information */
3738             FIXME("Didn't expect the destination to have a normal\n");
3739             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3740             if(dest_conv) {
3741                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3742             }
3743         }
3744
3745         if (DestFVF & WINED3DFVF_DIFFUSE) {
3746             DWORD *color_d = 
3747               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
3748             if(!color_d) {
3749                 static BOOL warned = FALSE;
3750
3751                 if(!warned) {
3752                     ERR("No diffuse color in source, but destination has one\n");
3753                     warned = TRUE;
3754                 }
3755
3756                 *( (DWORD *) dest_ptr) = 0xffffffff;
3757                 dest_ptr += sizeof(DWORD);
3758
3759                 if(dest_conv) {
3760                     *( (DWORD *) dest_conv) = 0xffffffff;
3761                     dest_conv += sizeof(DWORD);
3762                 }
3763             }
3764             else {
3765                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3766                 if(dest_conv) {
3767                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
3768                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3769                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3770                     dest_conv += sizeof(DWORD);
3771                 }
3772             }
3773         }
3774
3775         if (DestFVF & WINED3DFVF_SPECULAR) { 
3776             /* What's the color value in the feedback buffer? */
3777             DWORD *color_s = 
3778               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
3779             if(!color_s) {
3780                 static BOOL warned = FALSE;
3781
3782                 if(!warned) {
3783                     ERR("No specular color in source, but destination has one\n");
3784                     warned = TRUE;
3785                 }
3786
3787                 *( (DWORD *) dest_ptr) = 0xFF000000;
3788                 dest_ptr += sizeof(DWORD);
3789
3790                 if(dest_conv) {
3791                     *( (DWORD *) dest_conv) = 0xFF000000;
3792                     dest_conv += sizeof(DWORD);
3793                 }
3794             }
3795             else {
3796                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3797                 if(dest_conv) {
3798                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
3799                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
3800                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
3801                     dest_conv += sizeof(DWORD);
3802                 }
3803             }
3804         }
3805
3806         for (tex_index = 0; tex_index < numTextures; tex_index++) {
3807             float *tex_coord =
3808               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
3809                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
3810             if(!tex_coord) {
3811                 ERR("No source texture, but destination requests one\n");
3812                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3813                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3814             }
3815             else {
3816                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3817                 if(dest_conv) {
3818                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3819                 }
3820             }
3821         }
3822     }
3823
3824     if(dest_conv) {
3825         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3826         checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
3827         GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
3828                                       dwCount * get_flexible_vertex_size(DestFVF),
3829                                       dest_conv_addr));
3830         checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
3831         HeapFree(GetProcessHeap(), 0, dest_conv_addr);
3832     }
3833
3834     LEAVE_GL();
3835
3836     return WINED3D_OK;
3837 }
3838 #undef copy_and_next
3839
3840 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexDeclaration* pVertexDecl, DWORD Flags) {
3841     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3842     WineDirect3DVertexStridedData strided;
3843     BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP;
3844     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
3845
3846     if(pVertexDecl) {
3847         ERR("Output vertex declaration not implemented yet\n");
3848     }
3849
3850     /* Need any context to write to the vbo. In a non-multithreaded environment a context is there anyway,
3851      * and this call is quite performance critical, so don't call needlessly
3852      */
3853     if(This->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) {
3854         ENTER_GL();
3855         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
3856         LEAVE_GL();
3857     }
3858
3859     /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
3860      * control the streamIsUP flag, thus restore it afterwards.
3861      */
3862     This->stateBlock->streamIsUP = FALSE;
3863     memset(&strided, 0, sizeof(strided));
3864     if(This->stateBlock->vertexDecl) {
3865         primitiveDeclarationConvertToStridedData(iface, FALSE, &strided, &vbo);
3866     } else {
3867         primitiveConvertToStridedData(iface, &strided, &vbo);
3868     }
3869     This->stateBlock->streamIsUP = streamWasUP;
3870
3871     if(vbo || SrcStartIndex) {
3872         unsigned int i;
3873         /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcesVerticse are
3874          * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the strided structure
3875          *
3876          * Also get the start index in, but only loop over all elements if there's something to add at all.
3877          */
3878 #define FIXSRC(type) \
3879         if(strided.u.s.type.VBO) { \
3880             IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[strided.u.s.type.streamNo]; \
3881             strided.u.s.type.VBO = 0; \
3882             strided.u.s.type.lpData = (BYTE *) ((unsigned long) strided.u.s.type.lpData + (unsigned long) vb->resource.allocatedMemory); \
3883             ENTER_GL(); \
3884             GL_EXTCALL(glDeleteBuffersARB(1, &vb->vbo)); \
3885             vb->vbo = 0; \
3886             LEAVE_GL(); \
3887         } \
3888         if(strided.u.s.type.lpData) { \
3889             strided.u.s.type.lpData += strided.u.s.type.dwStride * SrcStartIndex; \
3890         }
3891         FIXSRC(position);
3892         FIXSRC(blendWeights);
3893         FIXSRC(blendMatrixIndices);
3894         FIXSRC(normal);
3895         FIXSRC(pSize);
3896         FIXSRC(diffuse);
3897         FIXSRC(specular);
3898         for(i = 0; i < WINED3DDP_MAXTEXCOORD; i++) {
3899             FIXSRC(texCoords[i]);
3900         }
3901         FIXSRC(position2);
3902         FIXSRC(normal2);
3903         FIXSRC(tangent);
3904         FIXSRC(binormal);
3905         FIXSRC(tessFactor);
3906         FIXSRC(fog);
3907         FIXSRC(depth);
3908         FIXSRC(sample);
3909 #undef FIXSRC
3910     }
3911
3912     return process_vertices_strided(This, DestIndex, VertexCount, &strided, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
3913 }
3914
3915 /*****
3916  * Get / Set Texture Stage States
3917  * TODO: Verify against dx9 definitions
3918  *****/
3919 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3920     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3921     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
3922
3923     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3924
3925     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3926
3927     if (Stage >= MAX_TEXTURES) {
3928         WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring\n", Stage, MAX_TEXTURES - 1);
3929         return WINED3D_OK;
3930     }
3931
3932     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3933     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
3934     This->updateStateBlock->textureState[Stage][Type]         = Value;
3935
3936     if (This->isRecordingState) {
3937         TRACE("Recording... not performing anything\n");
3938         return WINED3D_OK;
3939     }
3940
3941     /* Checked after the assignments to allow proper stateblock recording */
3942     if(oldValue == Value) {
3943         TRACE("App is setting the old value over, nothing to do\n");
3944         return WINED3D_OK;
3945     }
3946
3947     if(Stage > This->stateBlock->lowest_disabled_stage &&
3948        StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
3949         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
3950          * Changes in other states are important on disabled stages too
3951          */
3952         return WINED3D_OK;
3953     }
3954
3955     if(Type == WINED3DTSS_COLOROP) {
3956         int i;
3957
3958         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
3959             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
3960              * they have to be disabled
3961              *
3962              * The current stage is dirtified below.
3963              */
3964             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
3965                 TRACE("Additionally dirtifying stage %d\n", i);
3966                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3967             }
3968             This->stateBlock->lowest_disabled_stage = Stage;
3969             TRACE("New lowest disabled: %d\n", Stage);
3970         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
3971             /* Previously disabled stage enabled. Stages above it may need enabling
3972              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
3973              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
3974              *
3975              * Again stage Stage doesn't need to be dirtified here, it is handled below.
3976              */
3977
3978             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
3979                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
3980                     break;
3981                 }
3982                 TRACE("Additionally dirtifying stage %d due to enable\n", i);
3983                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3984             }
3985             This->stateBlock->lowest_disabled_stage = i;
3986             TRACE("New lowest disabled: %d\n", i);
3987         }
3988         if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3989             /* TODO: Built a stage -> texture unit mapping for register combiners */
3990         }
3991     }
3992
3993     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
3994
3995     return WINED3D_OK;
3996 }
3997
3998 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3999     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4000     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4001     *pValue = This->updateStateBlock->textureState[Stage][Type];
4002     return WINED3D_OK;
4003 }
4004
4005 /*****
4006  * Get / Set Texture
4007  *****/
4008 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4009
4010     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4011     IWineD3DBaseTexture   *oldTexture;
4012
4013     oldTexture = This->updateStateBlock->textures[Stage];
4014     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
4015
4016 #if 0 /* TODO: check so vertex textures */
4017     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4018         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4019         return WINED3D_OK;
4020     }
4021 #endif
4022
4023     if(pTexture != NULL) {
4024         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
4025          */
4026         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
4027             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4028             return WINED3DERR_INVALIDCALL;
4029         }
4030         This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
4031     }
4032
4033     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
4034     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4035
4036     This->updateStateBlock->set.textures[Stage]     = TRUE;
4037     This->updateStateBlock->changed.textures[Stage] = TRUE;
4038     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4039     This->updateStateBlock->textures[Stage]         = pTexture;
4040
4041     /* Handle recording of state blocks */
4042     if (This->isRecordingState) {
4043         TRACE("Recording... not performing anything\n");
4044         return WINED3D_OK;
4045     }
4046
4047     if(oldTexture == pTexture) {
4048         TRACE("App is setting the same texture again, nothing to do\n");
4049         return WINED3D_OK;
4050     }
4051
4052     /** NOTE: MSDN says that setTexture increases the reference count,
4053     * and the the application must set the texture back to null (or have a leaky application),
4054     * This means we should pass the refcount up to the parent
4055      *******************************/
4056     if (NULL != This->updateStateBlock->textures[Stage]) {
4057         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
4058         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
4059
4060         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4061         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
4062             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4063              * so the COLOROP and ALPHAOP have to be dirtified.
4064              */
4065             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4066             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4067         }
4068         if(bindCount == 1) {
4069             new->baseTexture.sampler = Stage;
4070         }
4071         /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
4072
4073     }
4074
4075     if (NULL != oldTexture) {
4076         IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
4077         LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
4078
4079         IWineD3DBaseTexture_Release(oldTexture);
4080         if(pTexture == NULL && Stage < MAX_TEXTURES) {
4081             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4082             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4083         }
4084
4085         if(bindCount && old->baseTexture.sampler == Stage) {
4086             int i;
4087             /* Have to do a search for the other sampler(s) where the texture is bound to
4088              * Shouldn't happen as long as apps bind a texture only to one stage
4089              */
4090             TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
4091             for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
4092                 if(This->updateStateBlock->textures[i] == oldTexture) {
4093                     old->baseTexture.sampler = i;
4094                     break;
4095                 }
4096             }
4097         }
4098     }
4099
4100     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
4101
4102     return WINED3D_OK;
4103 }
4104
4105 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4106     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4107     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4108
4109     *ppTexture=This->stateBlock->textures[Stage];
4110     if (*ppTexture)
4111         IWineD3DBaseTexture_AddRef(*ppTexture);
4112
4113     return WINED3D_OK;
4114 }
4115
4116 /*****
4117  * Get Back Buffer
4118  *****/
4119 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4120                                                 IWineD3DSurface **ppBackBuffer) {
4121     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4122     IWineD3DSwapChain *swapChain;
4123     HRESULT hr;
4124
4125     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4126
4127     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4128     if (hr == WINED3D_OK) {
4129         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4130             IWineD3DSwapChain_Release(swapChain);
4131     } else {
4132         *ppBackBuffer = NULL;
4133     }
4134     return hr;
4135 }
4136
4137 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4138     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4139     WARN("(%p) : stub, calling idirect3d for now\n", This);
4140     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4141 }
4142
4143 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4144     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4145     IWineD3DSwapChain *swapChain;
4146     HRESULT hr;
4147
4148     if(iSwapChain > 0) {
4149         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4150         if (hr == WINED3D_OK) {
4151             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4152             IWineD3DSwapChain_Release(swapChain);
4153         } else {
4154             FIXME("(%p) Error getting display mode\n", This);
4155         }
4156     } else {
4157         /* Don't read the real display mode,
4158            but return the stored mode instead. X11 can't change the color
4159            depth, and some apps are pretty angry if they SetDisplayMode from
4160            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4161
4162            Also don't relay to the swapchain because with ddraw it's possible
4163            that there isn't a swapchain at all */
4164         pMode->Width = This->ddraw_width;
4165         pMode->Height = This->ddraw_height;
4166         pMode->Format = This->ddraw_format;
4167         pMode->RefreshRate = 0;
4168         hr = WINED3D_OK;
4169     }
4170
4171     return hr;
4172 }
4173
4174 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4175     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4176     TRACE("(%p)->(%p)\n", This, hWnd);
4177
4178     if(This->ddraw_fullscreen) {
4179         if(This->ddraw_window && This->ddraw_window != hWnd) {
4180             IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
4181         }
4182         if(hWnd && This->ddraw_window != hWnd) {
4183             IWineD3DDeviceImpl_SetupFullscreenWindow(iface, hWnd);
4184         }
4185     }
4186
4187     This->ddraw_window = hWnd;
4188     return WINED3D_OK;
4189 }
4190
4191 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4192     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4193     TRACE("(%p)->(%p)\n", This, hWnd);
4194
4195     *hWnd = This->ddraw_window;
4196     return WINED3D_OK;
4197 }
4198
4199 /*****
4200  * Stateblock related functions
4201  *****/
4202
4203 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4204     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4205     IWineD3DStateBlockImpl *object;
4206     HRESULT temp_result;
4207     int i;
4208
4209     TRACE("(%p)\n", This);
4210     
4211     if (This->isRecordingState) {
4212         return WINED3DERR_INVALIDCALL;
4213     }
4214     
4215     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4216     if (NULL == object ) {
4217         FIXME("(%p)Error allocating memory for stateblock\n", This);
4218         return E_OUTOFMEMORY;
4219     }
4220     TRACE("(%p) created object %p\n", This, object);
4221     object->wineD3DDevice= This;
4222     /** FIXME: object->parent       = parent; **/
4223     object->parent       = NULL;
4224     object->blockType    = WINED3DSBT_ALL;
4225     object->ref          = 1;
4226     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4227
4228     for(i = 0; i < LIGHTMAP_SIZE; i++) {
4229         list_init(&object->lightMap[i]);
4230     }
4231
4232     temp_result = allocate_shader_constants(object);
4233     if (WINED3D_OK != temp_result)
4234         return temp_result;
4235
4236     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4237     This->updateStateBlock = object;
4238     This->isRecordingState = TRUE;
4239
4240     TRACE("(%p) recording stateblock %p\n",This , object);
4241     return WINED3D_OK;
4242 }
4243
4244 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4245     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4246
4247     if (!This->isRecordingState) {
4248         FIXME("(%p) not recording! returning error\n", This);
4249         *ppStateBlock = NULL;
4250         return WINED3DERR_INVALIDCALL;
4251     }
4252
4253     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4254     This->isRecordingState = FALSE;
4255     This->updateStateBlock = This->stateBlock;
4256     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4257     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4258     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4259     return WINED3D_OK;
4260 }
4261
4262 /*****
4263  * Scene related functions
4264  *****/
4265 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4266     /* At the moment we have no need for any functionality at the beginning
4267        of a scene                                                          */
4268     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4269     TRACE("(%p)\n", This);
4270
4271     if(This->inScene) {
4272         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4273         return WINED3DERR_INVALIDCALL;
4274     }
4275     This->inScene = TRUE;
4276     return WINED3D_OK;
4277 }
4278
4279 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4280     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4281     TRACE("(%p)\n", This);
4282
4283     if(!This->inScene) {
4284         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4285         return WINED3DERR_INVALIDCALL;
4286     }
4287
4288     ENTER_GL();
4289     if(This->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) {
4290         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4291     }
4292     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4293     glFlush();
4294     checkGLcall("glFlush");
4295     LEAVE_GL();
4296
4297     This->inScene = FALSE;
4298     return WINED3D_OK;
4299 }
4300
4301 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4302                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4303                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4304     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4305     IWineD3DSwapChain *swapChain = NULL;
4306     int i;
4307     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4308
4309     TRACE("(%p) Presenting the frame\n", This);
4310
4311     for(i = 0 ; i < swapchains ; i ++) {
4312
4313         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4314         TRACE("presentinng chain %d, %p\n", i, swapChain);
4315         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4316         IWineD3DSwapChain_Release(swapChain);
4317     }
4318
4319     return WINED3D_OK;
4320 }
4321
4322 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4323                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4324     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4325     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0];
4326
4327     GLbitfield     glMask = 0;
4328     unsigned int   i;
4329     CONST WINED3DRECT* curRect;
4330
4331     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This,
4332           Count, pRects, Flags, Color, Z, Stencil);
4333
4334     if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
4335         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4336         /* TODO: What about depth stencil buffers without stencil bits? */
4337         return WINED3DERR_INVALIDCALL;
4338     }
4339
4340     ENTER_GL();
4341     /* This is for offscreen rendering as well as for multithreading, thus activate the set render target
4342      * and not the last active one.
4343      */
4344
4345     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4346         apply_fbo_state(iface);
4347     }
4348
4349     ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
4350
4351     glEnable(GL_SCISSOR_TEST);
4352     checkGLcall("glEnable GL_SCISSOR_TEST");
4353     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
4354     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
4355
4356     if (Count > 0 && pRects) {
4357         curRect = pRects;
4358     } else {
4359         curRect = NULL;
4360     }
4361
4362     /* Only set the values up once, as they are not changing */
4363     if (Flags & WINED3DCLEAR_STENCIL) {
4364         glClearStencil(Stencil);
4365         checkGLcall("glClearStencil");
4366         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4367         glStencilMask(0xFFFFFFFF);
4368     }
4369
4370     if (Flags & WINED3DCLEAR_ZBUFFER) {
4371         glDepthMask(GL_TRUE);
4372         glClearDepth(Z);
4373         checkGLcall("glClearDepth");
4374         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4375         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4376     }
4377
4378     if (Flags & WINED3DCLEAR_TARGET) {
4379         TRACE("Clearing screen with glClear to color %x\n", Color);
4380         glClearColor(D3DCOLOR_R(Color),
4381                      D3DCOLOR_G(Color),
4382                      D3DCOLOR_B(Color),
4383                      D3DCOLOR_A(Color));
4384         checkGLcall("glClearColor");
4385
4386         /* Clear ALL colors! */
4387         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4388         glMask = glMask | GL_COLOR_BUFFER_BIT;
4389     }
4390
4391     if (!curRect) {
4392         /* In drawable flag is set below */
4393
4394         glScissor(This->stateBlock->viewport.X,
4395                   (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4396                   (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4397                    This->stateBlock->viewport.Width,
4398                    This->stateBlock->viewport.Height);
4399         checkGLcall("glScissor");
4400         glClear(glMask);
4401         checkGLcall("glClear");
4402     } else {
4403         if(!(target->Flags & SFLAG_INDRAWABLE) &&
4404            !(wined3d_settings.offscreen_rendering_mode == ORM_FBO && This->render_offscreen && target->Flags & SFLAG_INTEXTURE)) {
4405
4406             if(curRect[0].x1 > 0 || curRect[0].y1 > 0 ||
4407                curRect[0].x2 < target->currentDesc.Width ||
4408                curRect[0].y2 < target->currentDesc.Height) {
4409                 TRACE("Partial clear, and surface not in drawable. Blitting texture to drawable\n");
4410                 blt_to_drawable(This, target);
4411             }
4412         }
4413
4414         /* Now process each rect in turn */
4415         for (i = 0; i < Count; i++) {
4416             /* Note gl uses lower left, width/height */
4417             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4418                   curRect[i].x1, curRect[i].y1, curRect[i].x2, curRect[i].y2,
4419                   curRect[i].x1, (target->currentDesc.Height - curRect[i].y2),
4420                   curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4421
4422             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4423              * The rectangle is not cleared, no error is returned, but further rectanlges are
4424              * still cleared if they are valid
4425              */
4426             if(curRect[i].x1 > curRect[i].x2 || curRect[i].y1 > curRect[i].y2) {
4427                 TRACE("Rectangle with negative dimensions, ignoring\n");
4428                 continue;
4429             }
4430
4431             if(This->render_offscreen) {
4432                 glScissor(curRect[i].x1, curRect[i].y1,
4433                           curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4434             } else {
4435                 glScissor(curRect[i].x1, target->currentDesc.Height - curRect[i].y2,
4436                           curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4437             }
4438             checkGLcall("glScissor");
4439
4440             glClear(glMask);
4441             checkGLcall("glClear");
4442         }
4443     }
4444
4445     /* Restore the old values (why..?) */
4446     if (Flags & WINED3DCLEAR_STENCIL) {
4447         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4448     }
4449     if (Flags & WINED3DCLEAR_TARGET) {
4450         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
4451         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4452                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4453                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4454                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4455     }
4456
4457     LEAVE_GL();
4458
4459     /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
4460      * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
4461      */
4462     if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4463         target->Flags |= SFLAG_INTEXTURE;
4464         target->Flags &= ~SFLAG_INSYSMEM;
4465     } else {
4466         target->Flags |= SFLAG_INDRAWABLE;
4467         target->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INSYSMEM);
4468     }
4469     return WINED3D_OK;
4470 }
4471
4472 /*****
4473  * Drawing functions
4474  *****/
4475 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4476                                                 UINT PrimitiveCount) {
4477
4478     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4479
4480     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4481                                debug_d3dprimitivetype(PrimitiveType),
4482                                StartVertex, PrimitiveCount);
4483
4484     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4485     if(This->stateBlock->streamIsUP) {
4486         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4487         This->stateBlock->streamIsUP = FALSE;
4488     }
4489
4490     if(This->stateBlock->loadBaseVertexIndex != 0) {
4491         This->stateBlock->loadBaseVertexIndex = 0;
4492         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4493     }
4494     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4495     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4496                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4497     return WINED3D_OK;
4498 }
4499
4500 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4501 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4502                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4503                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4504
4505     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4506     UINT                 idxStride = 2;
4507     IWineD3DIndexBuffer *pIB;
4508     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4509     GLuint vbo;
4510
4511     pIB = This->stateBlock->pIndexData;
4512     if (!pIB) {
4513         /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4514          * without an index buffer set. (The first time at least...)
4515          * D3D8 simply dies, but I doubt it can do much harm to return
4516          * D3DERR_INVALIDCALL there as well. */
4517         ERR("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This);
4518         return WINED3DERR_INVALIDCALL;
4519     }
4520
4521     if(This->stateBlock->streamIsUP) {
4522         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4523         This->stateBlock->streamIsUP = FALSE;
4524     }
4525     vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
4526
4527     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4528           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4529           minIndex, NumVertices, startIndex, primCount);
4530
4531     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4532     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4533         idxStride = 2;
4534     } else {
4535         idxStride = 4;
4536     }
4537
4538     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4539         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4540         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4541     }
4542
4543     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4544                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4545
4546     return WINED3D_OK;
4547 }
4548
4549 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4550                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4551                                                     UINT VertexStreamZeroStride) {
4552     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4553
4554     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4555              debug_d3dprimitivetype(PrimitiveType),
4556              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4557
4558     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4559     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4560     This->stateBlock->streamOffset[0] = 0;
4561     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4562     This->stateBlock->streamIsUP = TRUE;
4563     This->stateBlock->loadBaseVertexIndex = 0;
4564
4565     /* TODO: Only mark dirty if drawing from a different UP address */
4566     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4567
4568     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4569                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4570
4571     /* MSDN specifies stream zero settings must be set to NULL */
4572     This->stateBlock->streamStride[0] = 0;
4573     This->stateBlock->streamSource[0] = NULL;
4574
4575     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4576      * the new stream sources or use UP drawing again
4577      */
4578     return WINED3D_OK;
4579 }
4580
4581 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4582                                                              UINT MinVertexIndex, UINT NumVertices,
4583                                                              UINT PrimitiveCount, CONST void* pIndexData,
4584                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4585                                                              UINT VertexStreamZeroStride) {
4586     int                 idxStride;
4587     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4588
4589     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4590              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4591              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4592              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4593
4594     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4595         idxStride = 2;
4596     } else {
4597         idxStride = 4;
4598     }
4599
4600     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4601     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4602     This->stateBlock->streamIsUP = TRUE;
4603     This->stateBlock->streamOffset[0] = 0;
4604     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4605
4606     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4607     This->stateBlock->baseVertexIndex = 0;
4608     This->stateBlock->loadBaseVertexIndex = 0;
4609     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4610     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4611     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4612
4613     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4614
4615     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4616     This->stateBlock->streamSource[0] = NULL;
4617     This->stateBlock->streamStride[0] = 0;
4618     This->stateBlock->pIndexData = NULL;
4619     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4620      * SetStreamSource to specify a vertex buffer
4621      */
4622
4623     return WINED3D_OK;
4624 }
4625
4626 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4627     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4628
4629     /* Mark the state dirty until we have nicer tracking
4630      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4631      * that value.
4632      */
4633     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4634     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4635     This->stateBlock->baseVertexIndex = 0;
4636     This->up_strided = DrawPrimStrideData;
4637     This->stateBlock->streamIsUP = TRUE;
4638     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4639     This->up_strided = NULL;
4640     return WINED3D_OK;
4641 }
4642  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4643 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4644     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4645     HRESULT hr = WINED3D_OK;
4646     WINED3DRESOURCETYPE sourceType;
4647     WINED3DRESOURCETYPE destinationType;
4648     int i ,levels;
4649
4650     /* TODO: think about moving the code into IWineD3DBaseTexture  */
4651
4652     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4653
4654     /* verify that the source and destination textures aren't NULL */
4655     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4656         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4657              This, pSourceTexture, pDestinationTexture);
4658         hr = WINED3DERR_INVALIDCALL;
4659     }
4660
4661     if (pSourceTexture == pDestinationTexture) {
4662         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4663              This, pSourceTexture, pDestinationTexture);
4664         hr = WINED3DERR_INVALIDCALL;
4665     }
4666     /* Verify that the source and destination textures are the same type */
4667     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
4668     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4669
4670     if (sourceType != destinationType) {
4671         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4672              This);
4673         hr = WINED3DERR_INVALIDCALL;
4674     }
4675
4676     /* check that both textures have the identical numbers of levels  */
4677     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4678         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4679         hr = WINED3DERR_INVALIDCALL;
4680     }
4681
4682     if (WINED3D_OK == hr) {
4683
4684         /* Make sure that the destination texture is loaded */
4685         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4686
4687         /* Update every surface level of the texture */
4688         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4689
4690         switch (sourceType) {
4691         case WINED3DRTYPE_TEXTURE:
4692             {
4693                 IWineD3DSurface *srcSurface;
4694                 IWineD3DSurface *destSurface;
4695
4696                 for (i = 0 ; i < levels ; ++i) {
4697                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
4698                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4699                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4700                     IWineD3DSurface_Release(srcSurface);
4701                     IWineD3DSurface_Release(destSurface);
4702                     if (WINED3D_OK != hr) {
4703                         WARN("(%p) : Call to update surface failed\n", This);
4704                         return hr;
4705                     }
4706                 }
4707             }
4708             break;
4709         case WINED3DRTYPE_CUBETEXTURE:
4710             {
4711                 IWineD3DSurface *srcSurface;
4712                 IWineD3DSurface *destSurface;
4713                 WINED3DCUBEMAP_FACES faceType;
4714
4715                 for (i = 0 ; i < levels ; ++i) {
4716                     /* Update each cube face */
4717                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4718                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
4719                         if (WINED3D_OK != hr) {
4720                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4721                         } else {
4722                             TRACE("Got srcSurface %p\n", srcSurface);
4723                         }
4724                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4725                         if (WINED3D_OK != hr) {
4726                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4727                         } else {
4728                             TRACE("Got desrSurface %p\n", destSurface);
4729                         }
4730                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4731                         IWineD3DSurface_Release(srcSurface);
4732                         IWineD3DSurface_Release(destSurface);
4733                         if (WINED3D_OK != hr) {
4734                             WARN("(%p) : Call to update surface failed\n", This);
4735                             return hr;
4736                         }
4737                     }
4738                 }
4739             }
4740             break;
4741 #if 0 /* TODO: Add support for volume textures */
4742         case WINED3DRTYPE_VOLUMETEXTURE:
4743             {
4744                 IWineD3DVolume  srcVolume  = NULL;
4745                 IWineD3DSurface destVolume = NULL;
4746
4747                 for (i = 0 ; i < levels ; ++i) {
4748                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
4749                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4750                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4751                     IWineD3DVolume_Release(srcSurface);
4752                     IWineD3DVolume_Release(destSurface);
4753                     if (WINED3D_OK != hr) {
4754                         WARN("(%p) : Call to update volume failed\n", This);
4755                         return hr;
4756                     }
4757                 }
4758             }
4759             break;
4760 #endif
4761         default:
4762             FIXME("(%p) : Unsupported source and destination type\n", This);
4763             hr = WINED3DERR_INVALIDCALL;
4764         }
4765     }
4766
4767     return hr;
4768 }
4769
4770 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4771     IWineD3DSwapChain *swapChain;
4772     HRESULT hr;
4773     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4774     if(hr == WINED3D_OK) {
4775         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4776                 IWineD3DSwapChain_Release(swapChain);
4777     }
4778     return hr;
4779 }
4780
4781 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4782     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4783     /* return a sensible default */
4784     *pNumPasses = 1;
4785     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
4786     FIXME("(%p) : stub\n", This);
4787     return WINED3D_OK;
4788 }
4789
4790 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4791     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4792     int j;
4793     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4794     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4795         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4796         return WINED3DERR_INVALIDCALL;
4797     }
4798     for (j = 0; j < 256; ++j) {
4799         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
4800         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4801         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
4802         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4803     }
4804     TRACE("(%p) : returning\n", This);
4805     return WINED3D_OK;
4806 }
4807
4808 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4809     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4810     int j;
4811     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4812     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4813         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4814         return WINED3DERR_INVALIDCALL;
4815     }
4816     for (j = 0; j < 256; ++j) {
4817         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
4818         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4819         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
4820         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4821     }
4822     TRACE("(%p) : returning\n", This);
4823     return WINED3D_OK;
4824 }
4825
4826 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4827     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4828     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4829     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4830         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4831         return WINED3DERR_INVALIDCALL;
4832     }
4833     /*TODO: stateblocks */
4834     This->currentPalette = PaletteNumber;
4835     TRACE("(%p) : returning\n", This);
4836     return WINED3D_OK;
4837 }
4838
4839 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4840     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4841     if (PaletteNumber == NULL) {
4842         WARN("(%p) : returning Invalid Call\n", This);
4843         return WINED3DERR_INVALIDCALL;
4844     }
4845     /*TODO: stateblocks */
4846     *PaletteNumber = This->currentPalette;
4847     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
4848     return WINED3D_OK;
4849 }
4850
4851 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4852     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4853     static BOOL showFixmes = TRUE;
4854     if (showFixmes) {
4855         FIXME("(%p) : stub\n", This);
4856         showFixmes = FALSE;
4857     }
4858
4859     This->softwareVertexProcessing = bSoftware;
4860     return WINED3D_OK;
4861 }
4862
4863
4864 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4865     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4866     static BOOL showFixmes = TRUE;
4867     if (showFixmes) {
4868         FIXME("(%p) : stub\n", This);
4869         showFixmes = FALSE;
4870     }
4871     return This->softwareVertexProcessing;
4872 }
4873
4874
4875 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
4876     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4877     IWineD3DSwapChain *swapChain;
4878     HRESULT hr;
4879
4880     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4881
4882     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4883     if(hr == WINED3D_OK){
4884         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4885         IWineD3DSwapChain_Release(swapChain);
4886     }else{
4887         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
4888     }
4889     return hr;
4890 }
4891
4892
4893 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4894     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4895     static BOOL showfixmes = TRUE;
4896     if(nSegments != 0.0f) {
4897         if( showfixmes) {
4898             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4899             showfixmes = FALSE;
4900         }
4901     }
4902     return WINED3D_OK;
4903 }
4904
4905 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4906     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4907     static BOOL showfixmes = TRUE;
4908     if( showfixmes) {
4909         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4910         showfixmes = FALSE;
4911     }
4912     return 0.0f;
4913 }
4914
4915 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4916     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
4917     /** TODO: remove casts to IWineD3DSurfaceImpl
4918      *       NOTE: move code to surface to accomplish this
4919       ****************************************/
4920     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
4921     int srcWidth, srcHeight;
4922     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4923     WINED3DFORMAT destFormat, srcFormat;
4924     UINT          destSize;
4925     int srcLeft, destLeft, destTop;
4926     WINED3DPOOL       srcPool, destPool;
4927     int offset    = 0;
4928     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4929     glDescriptor *glDescription = NULL;
4930
4931     WINED3DSURFACE_DESC  winedesc;
4932
4933     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
4934     memset(&winedesc, 0, sizeof(winedesc));
4935     winedesc.Width  = &srcSurfaceWidth;
4936     winedesc.Height = &srcSurfaceHeight;
4937     winedesc.Pool   = &srcPool;
4938     winedesc.Format = &srcFormat;
4939
4940     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4941
4942     winedesc.Width  = &destSurfaceWidth;
4943     winedesc.Height = &destSurfaceHeight;
4944     winedesc.Pool   = &destPool;
4945     winedesc.Format = &destFormat;
4946     winedesc.Size   = &destSize;
4947
4948     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4949
4950     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
4951         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
4952         return WINED3DERR_INVALIDCALL;
4953     }
4954
4955     if (destFormat == WINED3DFMT_UNKNOWN) {
4956         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
4957         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
4958
4959         /* Get the update surface description */
4960         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4961     }
4962
4963     ENTER_GL();
4964
4965     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4966
4967     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4968         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
4969         checkGLcall("glActiveTextureARB");
4970     }
4971
4972     /* Make sure the surface is loaded and up to date */
4973     IWineD3DSurface_PreLoad(pDestinationSurface);
4974
4975     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4976
4977     /* this needs to be done in lines if the sourceRect != the sourceWidth */
4978     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
4979     srcHeight  = pSourceRect ? pSourceRect->bottom - pSourceRect->top   : srcSurfaceHeight;
4980     srcLeft    = pSourceRect ? pSourceRect->left : 0;
4981     destLeft   = pDestPoint  ? pDestPoint->x : 0;
4982     destTop    = pDestPoint  ? pDestPoint->y : 0;
4983
4984
4985     /* This function doesn't support compressed textures
4986     the pitch is just bytesPerPixel * width */
4987     if(srcWidth != srcSurfaceWidth  || srcLeft ){
4988         rowoffset = srcSurfaceWidth * pSrcSurface->bytesPerPixel;
4989         offset   += srcLeft * pSrcSurface->bytesPerPixel;
4990         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4991     }
4992     /* TODO DXT formats */
4993
4994     if(pSourceRect != NULL && pSourceRect->top != 0){
4995        offset +=  pSourceRect->top * srcSurfaceWidth * pSrcSurface->bytesPerPixel;
4996     }
4997     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4998     ,This
4999     ,glDescription->level
5000     ,destLeft
5001     ,destTop
5002     ,srcWidth
5003     ,srcHeight
5004     ,glDescription->glFormat
5005     ,glDescription->glType
5006     ,IWineD3DSurface_GetData(pSourceSurface)
5007     );
5008
5009     /* Sanity check */
5010     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5011
5012         /* need to lock the surface to get the data */
5013         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5014     }
5015
5016     /* TODO: Cube and volume support */
5017     if(rowoffset != 0){
5018         /* not a whole row so we have to do it a line at a time */
5019         int j;
5020
5021         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5022         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5023
5024         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5025
5026                 glTexSubImage2D(glDescription->target
5027                     ,glDescription->level
5028                     ,destLeft
5029                     ,j
5030                     ,srcWidth
5031                     ,1
5032                     ,glDescription->glFormat
5033                     ,glDescription->glType
5034                     ,data /* could be quicker using */
5035                 );
5036             data += rowoffset;
5037         }
5038
5039     } else { /* Full width, so just write out the whole texture */
5040
5041         if (WINED3DFMT_DXT1 == destFormat ||
5042             WINED3DFMT_DXT2 == destFormat ||
5043             WINED3DFMT_DXT3 == destFormat ||
5044             WINED3DFMT_DXT4 == destFormat ||
5045             WINED3DFMT_DXT5 == destFormat) {
5046             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5047                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5048                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5049                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5050                 } if (destFormat != srcFormat) {
5051                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5052                 } else {
5053                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5054                                                         glDescription->level,
5055                                                         glDescription->glFormatInternal,
5056                                                         srcWidth,
5057                                                         srcHeight,
5058                                                         0,
5059                                                         destSize,
5060                                                         IWineD3DSurface_GetData(pSourceSurface));
5061                 }
5062             } else {
5063                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5064             }
5065
5066
5067         } else {
5068             glTexSubImage2D(glDescription->target
5069                     ,glDescription->level
5070                     ,destLeft
5071                     ,destTop
5072                     ,srcWidth
5073                     ,srcHeight
5074                     ,glDescription->glFormat
5075                     ,glDescription->glType
5076                     ,IWineD3DSurface_GetData(pSourceSurface)
5077                 );
5078         }
5079      }
5080     checkGLcall("glTexSubImage2D");
5081
5082     LEAVE_GL();
5083
5084     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags &= ~SFLAG_INSYSMEM;
5085     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_INTEXTURE;
5086     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
5087
5088     return WINED3D_OK;
5089 }
5090
5091 /* Implementation details at http://developer.nvidia.com/attach/6494
5092 and
5093 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5094 hmm.. no longer supported use
5095 OpenGL evaluators or  tessellate surfaces within your application.
5096 */
5097
5098 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5099 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5100     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5101     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5102     FIXME("(%p) : Stub\n", This);
5103     return WINED3D_OK;
5104
5105 }
5106
5107 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5108 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5109     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5110     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5111     FIXME("(%p) : Stub\n", This);
5112     return WINED3D_OK;
5113 }
5114
5115 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5116     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5117     TRACE("(%p) Handle(%d)\n", This, Handle);
5118     FIXME("(%p) : Stub\n", This);
5119     return WINED3D_OK;
5120 }
5121
5122 static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) {
5123     HRESULT hr;
5124     IWineD3DSwapChain *swapchain;
5125
5126     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain);
5127     if (SUCCEEDED(hr)) {
5128         IWineD3DSwapChain_Release((IUnknown *)swapchain);
5129         return swapchain;
5130     }
5131
5132     return NULL;
5133 }
5134
5135 static void bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) {
5136     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5137
5138     if (!*fbo) {
5139         GL_EXTCALL(glGenFramebuffersEXT(1, fbo));
5140         checkGLcall("glGenFramebuffersEXT()");
5141     }
5142     GL_EXTCALL(glBindFramebufferEXT(target, *fbo));
5143     checkGLcall("glBindFramebuffer()");
5144 }
5145
5146 static void attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) {
5147     const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface;
5148     IWineD3DBaseTextureImpl *texture_impl;
5149     GLenum texttarget, target;
5150     GLint old_binding;
5151
5152     texttarget = surface_impl->glDescription.target;
5153     target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5154     glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5155
5156     IWineD3DSurface_PreLoad(surface);
5157
5158     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5159     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5160     glBindTexture(target, old_binding);
5161
5162     /* Update base texture states array */
5163     if (SUCCEEDED(IWineD3DSurface_GetContainer(surface, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
5164         texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
5165         texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
5166         if (texture_impl->baseTexture.bindCount) {
5167             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
5168         }
5169
5170         IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
5171     }
5172
5173     GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, surface_impl->glDescription.textureName, 0));
5174
5175     checkGLcall("attach_surface_fbo");
5176 }
5177
5178 static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONST WINED3DRECT *rect, WINED3DCOLOR color) {
5179     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5180     IWineD3DSwapChain *swapchain;
5181
5182     swapchain = get_swapchain(surface);
5183     if (swapchain) {
5184         GLenum buffer;
5185
5186         TRACE("Surface %p is onscreen\n", surface);
5187
5188         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5189         buffer = surface_get_gl_buffer(surface, swapchain);
5190         glDrawBuffer(buffer);
5191         checkGLcall("glDrawBuffer()");
5192     } else {
5193         TRACE("Surface %p is offscreen\n", surface);
5194         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->dst_fbo);
5195         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface);
5196     }
5197
5198     if (rect) {
5199         glEnable(GL_SCISSOR_TEST);
5200         if(!swapchain) {
5201             glScissor(rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1);
5202         } else {
5203             glScissor(rect->x1, ((IWineD3DSurfaceImpl *)surface)->currentDesc.Height - rect->y2,
5204                     rect->x2 - rect->x1, rect->y2 - rect->y1);
5205         }
5206         checkGLcall("glScissor");
5207     } else {
5208         glDisable(GL_SCISSOR_TEST);
5209     }
5210     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
5211
5212     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5213     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
5214
5215     glClearColor(D3DCOLOR_R(color), D3DCOLOR_G(color), D3DCOLOR_B(color), D3DCOLOR_A(color));
5216     glClear(GL_COLOR_BUFFER_BIT);
5217     checkGLcall("glClear");
5218
5219     if (This->render_offscreen) {
5220         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5221     } else {
5222         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5223         checkGLcall("glBindFramebuffer()");
5224     }
5225
5226     if (swapchain && surface == ((IWineD3DSwapChainImpl *)swapchain)->frontBuffer
5227             && ((IWineD3DSwapChainImpl *)swapchain)->backBuffer) {
5228         glDrawBuffer(GL_BACK);
5229         checkGLcall("glDrawBuffer()");
5230     }
5231 }
5232
5233 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
5234     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5235     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
5236     WINEDDBLTFX BltFx;
5237     TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This, pSurface, pRect, color);
5238
5239     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
5240         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5241         return WINED3DERR_INVALIDCALL;
5242     }
5243
5244     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5245         color_fill_fbo(iface, pSurface, pRect, color);
5246         return WINED3D_OK;
5247     } else {
5248         /* Just forward this to the DirectDraw blitting engine */
5249         memset(&BltFx, 0, sizeof(BltFx));
5250         BltFx.dwSize = sizeof(BltFx);
5251         BltFx.u5.dwFillColor = color;
5252         return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, WINEDDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE);
5253     }
5254 }
5255
5256 /* rendertarget and deptth stencil functions */
5257 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5258     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5259
5260     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5261         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5262         return WINED3DERR_INVALIDCALL;
5263     }
5264
5265     *ppRenderTarget = This->render_targets[RenderTargetIndex];
5266     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5267     /* Note inc ref on returned surface */
5268     if(*ppRenderTarget != NULL)
5269         IWineD3DSurface_AddRef(*ppRenderTarget);
5270     return WINED3D_OK;
5271 }
5272
5273 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
5274     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5275     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
5276     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
5277     IWineD3DSwapChainImpl *Swapchain;
5278     HRESULT hr;
5279
5280     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
5281
5282     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
5283     if(hr != WINED3D_OK) {
5284         ERR("Can't get the swapchain\n");
5285         return hr;
5286     }
5287
5288     /* Make sure to release the swapchain */
5289     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
5290
5291     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
5292         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5293         return WINED3DERR_INVALIDCALL;
5294     }
5295     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
5296         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5297         return WINED3DERR_INVALIDCALL;
5298     }
5299
5300     if(Swapchain->frontBuffer != Front) {
5301         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
5302
5303         if(Swapchain->frontBuffer)
5304             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
5305         Swapchain->frontBuffer = Front;
5306
5307         if(Swapchain->frontBuffer) {
5308             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
5309         }
5310     }
5311
5312     if(Back && !Swapchain->backBuffer) {
5313         /* We need memory for the back buffer array - only one back buffer this way */
5314         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
5315         if(!Swapchain->backBuffer) {
5316             ERR("Out of memory\n");
5317             return E_OUTOFMEMORY;
5318         }
5319     }
5320
5321     if(Swapchain->backBuffer[0] != Back) {
5322         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
5323
5324         /* What to do about the context here in the case of multithreading? Not sure.
5325          * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
5326          */
5327         ENTER_GL();
5328         if(!Swapchain->backBuffer[0]) {
5329             /* GL was told to draw to the front buffer at creation,
5330              * undo that
5331              */
5332             glDrawBuffer(GL_BACK);
5333             checkGLcall("glDrawBuffer(GL_BACK)");
5334             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
5335             Swapchain->presentParms.BackBufferCount = 1;
5336         } else if (!Back) {
5337             /* That makes problems - disable for now */
5338             /* glDrawBuffer(GL_FRONT); */
5339             checkGLcall("glDrawBuffer(GL_FRONT)");
5340             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
5341             Swapchain->presentParms.BackBufferCount = 0;
5342         }
5343         LEAVE_GL();
5344
5345         if(Swapchain->backBuffer[0])
5346             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
5347         Swapchain->backBuffer[0] = Back;
5348
5349         if(Swapchain->backBuffer[0]) {
5350             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5351         } else {
5352             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5353         }
5354
5355     }
5356
5357     return WINED3D_OK;
5358 }
5359
5360 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5361     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5362     *ppZStencilSurface = This->depthStencilBuffer;
5363     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5364
5365     if(*ppZStencilSurface != NULL) {
5366         /* Note inc ref on returned surface */
5367         IWineD3DSurface_AddRef(*ppZStencilSurface);
5368     }
5369     return WINED3D_OK;
5370 }
5371
5372 /* TODO: Handle stencil attachments */
5373 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5374     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5375     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5376
5377     TRACE("Set depth stencil to %p\n", depth_stencil);
5378
5379     if (depth_stencil_impl) {
5380         if (depth_stencil_impl->current_renderbuffer) {
5381             GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id));
5382             checkGLcall("glFramebufferRenderbufferEXT()");
5383         } else {
5384             IWineD3DBaseTextureImpl *texture_impl;
5385             GLenum texttarget, target;
5386             GLint old_binding = 0;
5387
5388             texttarget = depth_stencil_impl->glDescription.target;
5389             target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5390             glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5391
5392             IWineD3DSurface_PreLoad(depth_stencil);
5393
5394             glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5395             glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5396             glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5397             glBindTexture(target, old_binding);
5398
5399             /* Update base texture states array */
5400             if (SUCCEEDED(IWineD3DSurface_GetContainer(depth_stencil, &IID_IWineD3DBaseTexture, (void **)&texture_impl))) {
5401                 texture_impl->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
5402                 texture_impl->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
5403                 if (texture_impl->baseTexture.bindCount) {
5404                     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(texture_impl->baseTexture.sampler));
5405                 }
5406
5407                 IWineD3DBaseTexture_Release((IWineD3DBaseTexture *)texture_impl);
5408             }
5409
5410             GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5411             checkGLcall("glFramebufferTexture2DEXT()");
5412         }
5413     } else {
5414         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5415         checkGLcall("glFramebufferTexture2DEXT()");
5416     }
5417 }
5418
5419 static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5420     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5421     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5422
5423     TRACE("Set render target %u to %p\n", idx, render_target);
5424
5425     if (rtimpl) {
5426         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, idx, render_target);
5427         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5428     } else {
5429         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5430         checkGLcall("glFramebufferTexture2DEXT()");
5431
5432         This->draw_buffers[idx] = GL_NONE;
5433     }
5434 }
5435
5436 static void check_fbo_status(IWineD3DDevice *iface) {
5437     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5438     GLenum status;
5439
5440     status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
5441     if (status == GL_FRAMEBUFFER_COMPLETE_EXT) {
5442         TRACE("FBO complete\n");
5443     } else {
5444         FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status);
5445
5446         /* Dump the FBO attachments */
5447         if (status == GL_FRAMEBUFFER_UNSUPPORTED_EXT) {
5448             IWineD3DSurfaceImpl *attachment;
5449             int i;
5450
5451             for (i = 0; i < GL_LIMITS(buffers); ++i) {
5452                 attachment = (IWineD3DSurfaceImpl *)This->fbo_color_attachments[i];
5453                 if (attachment) {
5454                     FIXME("\tColor attachment %d: (%p) %s %ux%u\n", i, attachment, debug_d3dformat(attachment->resource.format),
5455                             attachment->pow2Width, attachment->pow2Height);
5456                 }
5457             }
5458             attachment = (IWineD3DSurfaceImpl *)This->fbo_depth_attachment;
5459             if (attachment) {
5460                 FIXME("\tDepth attachment: (%p) %s %ux%u\n", attachment, debug_d3dformat(attachment->resource.format),
5461                         attachment->pow2Width, attachment->pow2Height);
5462             }
5463         }
5464     }
5465 }
5466
5467 static BOOL depth_mismatch_fbo(IWineD3DDevice *iface) {
5468     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5469     IWineD3DSurfaceImpl *rt_impl = (IWineD3DSurfaceImpl *)This->render_targets[0];
5470     IWineD3DSurfaceImpl *ds_impl = (IWineD3DSurfaceImpl *)This->stencilBufferTarget;
5471
5472     if (!ds_impl) return FALSE;
5473
5474     if (ds_impl->current_renderbuffer) {
5475         return (rt_impl->pow2Width != ds_impl->current_renderbuffer->width ||
5476                 rt_impl->pow2Height != ds_impl->current_renderbuffer->height);
5477     }
5478
5479     return (rt_impl->pow2Width != ds_impl->pow2Width ||
5480             rt_impl->pow2Height != ds_impl->pow2Height);
5481 }
5482
5483 void apply_fbo_state(IWineD3DDevice *iface) {
5484     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5485     unsigned int i;
5486
5487     if (This->render_offscreen) {
5488         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5489
5490         /* Apply render targets */
5491         for (i = 0; i < GL_LIMITS(buffers); ++i) {
5492             IWineD3DSurface *render_target = This->render_targets[i];
5493             if (This->fbo_color_attachments[i] != render_target) {
5494                 set_render_target_fbo(iface, i, render_target);
5495                 This->fbo_color_attachments[i] = render_target;
5496             }
5497         }
5498
5499         /* Apply depth targets */
5500         if (This->fbo_depth_attachment != This->stencilBufferTarget || depth_mismatch_fbo(iface)) {
5501             unsigned int w = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Width;
5502             unsigned int h = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Height;
5503
5504             if (This->stencilBufferTarget) {
5505                 surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h);
5506             }
5507             set_depth_stencil_fbo(iface, This->stencilBufferTarget);
5508             This->fbo_depth_attachment = This->stencilBufferTarget;
5509         }
5510
5511         if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5512             GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5513             checkGLcall("glDrawBuffers()");
5514         } else {
5515             glDrawBuffer(This->draw_buffers[0]);
5516             checkGLcall("glDrawBuffer()");
5517         }
5518     } else {
5519         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5520     }
5521
5522     check_fbo_status(iface);
5523 }
5524
5525 void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect,
5526         IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) {
5527     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5528     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
5529     IWineD3DSwapChain *src_swapchain, *dst_swapchain;
5530     GLenum gl_filter;
5531
5532     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
5533             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
5534     TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2);
5535     TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2);
5536
5537     switch (filter) {
5538         case WINED3DTEXF_LINEAR:
5539             gl_filter = GL_LINEAR;
5540             break;
5541
5542         default:
5543             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
5544         case WINED3DTEXF_NONE:
5545         case WINED3DTEXF_POINT:
5546             gl_filter = GL_NEAREST;
5547             break;
5548     }
5549
5550     /* Attach src surface to src fbo */
5551     src_swapchain = get_swapchain(src_surface);
5552     ENTER_GL();
5553     if (src_swapchain) {
5554         GLenum buffer;
5555
5556         TRACE("Source surface %p is onscreen\n", src_surface);
5557         ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD);
5558
5559         GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0));
5560         buffer = surface_get_gl_buffer(src_surface, src_swapchain);
5561         glReadBuffer(buffer);
5562         checkGLcall("glReadBuffer()");
5563
5564         src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
5565         src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
5566     } else {
5567         TRACE("Source surface %p is offscreen\n", src_surface);
5568         bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo);
5569         attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
5570         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
5571         checkGLcall("glReadBuffer()");
5572     }
5573
5574     /* Attach dst surface to dst fbo */
5575     dst_swapchain = get_swapchain(dst_surface);
5576     if (dst_swapchain) {
5577         GLenum buffer;
5578
5579         TRACE("Destination surface %p is onscreen\n", dst_surface);
5580         ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD);
5581
5582         GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0));
5583         buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
5584         glDrawBuffer(buffer);
5585         checkGLcall("glDrawBuffer()");
5586
5587         dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
5588         dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
5589     } else {
5590         TRACE("Destination surface %p is offscreen\n", dst_surface);
5591
5592         /* No src or dst swapchain? Make sure some context is active(multithreading) */
5593         if(!src_swapchain) {
5594             ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5595         }
5596
5597         bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo);
5598         attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
5599         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
5600         checkGLcall("glDrawBuffer()");
5601     }
5602     glDisable(GL_SCISSOR_TEST);
5603     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
5604
5605     if (flip) {
5606         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
5607                 dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter));
5608         checkGLcall("glBlitFramebuffer()");
5609     } else {
5610         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
5611                 dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter));
5612         checkGLcall("glBlitFramebuffer()");
5613     }
5614
5615     if (This->render_offscreen) {
5616         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5617     } else {
5618         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5619         checkGLcall("glBindFramebuffer()");
5620     }
5621
5622     /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
5623     if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer
5624             && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) {
5625         glDrawBuffer(GL_BACK);
5626         checkGLcall("glDrawBuffer()");
5627     }
5628     LEAVE_GL();
5629 }
5630
5631 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5632     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5633     WINED3DVIEWPORT viewport;
5634
5635     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5636
5637     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5638         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5639         return WINED3DERR_INVALIDCALL;
5640     }
5641
5642     /* MSDN says that null disables the render target
5643     but a device must always be associated with a render target
5644     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5645
5646     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5647     for more details
5648     */
5649     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5650         FIXME("Trying to set render target 0 to NULL\n");
5651         return WINED3DERR_INVALIDCALL;
5652     }
5653     if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5654         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);
5655         return WINED3DERR_INVALIDCALL;
5656     }
5657
5658     /* If we are trying to set what we already have, don't bother */
5659     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5660         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5661         return WINED3D_OK;
5662     }
5663     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5664     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5665     This->render_targets[RenderTargetIndex] = pRenderTarget;
5666
5667     /* Render target 0 is special */
5668     if(RenderTargetIndex == 0) {
5669         /* Finally, reset the viewport as the MSDN states. */
5670         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5671         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5672         viewport.X      = 0;
5673         viewport.Y      = 0;
5674         viewport.MaxZ   = 1.0f;
5675         viewport.MinZ   = 0.0f;
5676         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5677         /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
5678          * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
5679          */
5680         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
5681
5682         /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
5683          * ctx properly.
5684          * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
5685          * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
5686          */
5687         ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
5688     }
5689     return WINED3D_OK;
5690 }
5691
5692 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5693     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5694     HRESULT  hr = WINED3D_OK;
5695     IWineD3DSurface *tmp;
5696
5697     TRACE("(%p) Swapping z-buffer\n",This);
5698
5699     if (pNewZStencil == This->stencilBufferTarget) {
5700         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5701     } else {
5702         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5703         * depending on the renter target implementation being used.
5704         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5705         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5706         * stencil buffer and incure an extra memory overhead
5707          ******************************************************/
5708
5709         tmp = This->stencilBufferTarget;
5710         This->stencilBufferTarget = pNewZStencil;
5711         This->depth_copy_state = WINED3D_DCS_NO_COPY;
5712         /* should we be calling the parent or the wined3d surface? */
5713         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5714         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5715         hr = WINED3D_OK;
5716
5717         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
5718             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5719             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
5720             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
5721             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
5722         }
5723     }
5724
5725     return hr;
5726 }
5727
5728 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5729                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5730     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5731     /* TODO: the use of Impl is deprecated. */
5732     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5733     WINED3DLOCKED_RECT lockedRect;
5734
5735     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5736
5737     /* some basic validation checks */
5738     if(This->cursorTexture) {
5739         ENTER_GL();
5740         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5741         glDeleteTextures(1, &This->cursorTexture);
5742         LEAVE_GL();
5743         This->cursorTexture = 0;
5744     }
5745
5746     if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
5747         This->haveHardwareCursor = TRUE;
5748     else
5749         This->haveHardwareCursor = FALSE;
5750
5751     if(pCursorBitmap) {
5752         WINED3DLOCKED_RECT rect;
5753
5754         /* MSDN: Cursor must be A8R8G8B8 */
5755         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5756             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5757             return WINED3DERR_INVALIDCALL;
5758         }
5759
5760         /* MSDN: Cursor must be smaller than the display mode */
5761         if(pSur->currentDesc.Width > This->ddraw_width ||
5762            pSur->currentDesc.Height > This->ddraw_height) {
5763             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);
5764             return WINED3DERR_INVALIDCALL;
5765         }
5766
5767         if (!This->haveHardwareCursor) {
5768             /* TODO: MSDN: Cursor sizes must be a power of 2 */
5769
5770             /* Do not store the surface's pointer because the application may
5771              * release it after setting the cursor image. Windows doesn't
5772              * addref the set surface, so we can't do this either without
5773              * creating circular refcount dependencies. Copy out the gl texture
5774              * instead.
5775              */
5776             This->cursorWidth = pSur->currentDesc.Width;
5777             This->cursorHeight = pSur->currentDesc.Height;
5778             if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
5779             {
5780                 const PixelFormatDesc *tableEntry = getFormatDescEntry(WINED3DFMT_A8R8G8B8);
5781                 char *mem, *bits = (char *)rect.pBits;
5782                 GLint intfmt = tableEntry->glInternal;
5783                 GLint format = tableEntry->glFormat;
5784                 GLint type = tableEntry->glType;
5785                 INT height = This->cursorHeight;
5786                 INT width = This->cursorWidth;
5787                 INT bpp = tableEntry->bpp;
5788                 INT i;
5789
5790                 /* Reformat the texture memory (pitch and width can be
5791                  * different) */
5792                 mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
5793                 for(i = 0; i < height; i++)
5794                     memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
5795                 IWineD3DSurface_UnlockRect(pCursorBitmap);
5796                 ENTER_GL();
5797
5798                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
5799                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
5800                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
5801                 }
5802
5803                 /* Make sure that a proper texture unit is selected */
5804                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
5805                     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5806                     checkGLcall("glActiveTextureARB");
5807                 }
5808                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
5809                 /* Create a new cursor texture */
5810                 glGenTextures(1, &This->cursorTexture);
5811                 checkGLcall("glGenTextures");
5812                 glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
5813                 checkGLcall("glBindTexture");
5814                 /* Copy the bitmap memory into the cursor texture */
5815                 glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
5816                 HeapFree(GetProcessHeap(), 0, mem);
5817                 checkGLcall("glTexImage2D");
5818
5819                 if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
5820                     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
5821                     checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
5822                 }
5823
5824                 LEAVE_GL();
5825             }
5826             else
5827             {
5828                 FIXME("A cursor texture was not returned.\n");
5829                 This->cursorTexture = 0;
5830             }
5831         }
5832         else
5833         {
5834             /* Draw a hardware cursor */
5835             ICONINFO cursorInfo;
5836             HCURSOR cursor;
5837             /* Create and clear maskBits because it is not needed for
5838              * 32-bit cursors.  32x32 bits split into 32-bit chunks == 32
5839              * chunks. */
5840             DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5841                 (pSur->currentDesc.Width * pSur->currentDesc.Height / 8));
5842             IWineD3DSurface_LockRect(pCursorBitmap, &lockedRect, NULL,
5843                                          WINED3DLOCK_NO_DIRTY_UPDATE |
5844                                          WINED3DLOCK_READONLY
5845             );
5846             TRACE("width: %i height: %i\n", pSur->currentDesc.Width,
5847                   pSur->currentDesc.Height);
5848
5849             cursorInfo.fIcon = FALSE;
5850             cursorInfo.xHotspot = XHotSpot;
5851             cursorInfo.yHotspot = YHotSpot;
5852             cursorInfo.hbmMask = CreateBitmap(pSur->currentDesc.Width,
5853                                               pSur->currentDesc.Height, 1,
5854                                               1, &maskBits);
5855             cursorInfo.hbmColor = CreateBitmap(pSur->currentDesc.Width,
5856                                                pSur->currentDesc.Height, 1,
5857                                                32, lockedRect.pBits);
5858             IWineD3DSurface_UnlockRect(pCursorBitmap);
5859             /* Create our cursor and clean up. */
5860             cursor = CreateIconIndirect(&cursorInfo);
5861             SetCursor(cursor);
5862             if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
5863             if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
5864             if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
5865             This->hardwareCursor = cursor;
5866             HeapFree(GetProcessHeap(), 0, maskBits);
5867         }
5868     }
5869
5870     This->xHotSpot = XHotSpot;
5871     This->yHotSpot = YHotSpot;
5872     return WINED3D_OK;
5873 }
5874
5875 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5876     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5877     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5878
5879     This->xScreenSpace = XScreenSpace;
5880     This->yScreenSpace = YScreenSpace;
5881
5882     return;
5883
5884 }
5885
5886 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5887     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5888     BOOL oldVisible = This->bCursorVisible;
5889     POINT pt;
5890
5891     TRACE("(%p) : visible(%d)\n", This, bShow);
5892
5893     /*
5894      * When ShowCursor is first called it should make the cursor appear at the OS's last
5895      * known cursor position.  Because of this, some applications just repetitively call
5896      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
5897      */
5898     GetCursorPos(&pt);
5899     This->xScreenSpace = pt.x;
5900     This->yScreenSpace = pt.y;
5901
5902     if (This->haveHardwareCursor) {
5903         This->bCursorVisible = bShow;
5904         if (bShow)
5905             SetCursor(This->hardwareCursor);
5906         else
5907             SetCursor(NULL);
5908     }
5909     else
5910     {
5911         if (This->cursorTexture)
5912             This->bCursorVisible = bShow;
5913     }
5914
5915     return oldVisible;
5916 }
5917
5918 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5919     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5920     TRACE("(%p) : state (%u)\n", This, This->state);
5921     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5922     switch (This->state) {
5923     case WINED3D_OK:
5924         return WINED3D_OK;
5925     case WINED3DERR_DEVICELOST:
5926         {
5927             ResourceList *resourceList  = This->resources;
5928             while (NULL != resourceList) {
5929                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5930                 return WINED3DERR_DEVICENOTRESET;
5931                 resourceList = resourceList->next;
5932             }
5933             return WINED3DERR_DEVICELOST;
5934         }
5935     case WINED3DERR_DRIVERINTERNALERROR:
5936         return WINED3DERR_DRIVERINTERNALERROR;
5937     }
5938
5939     /* Unknown state */
5940     return WINED3DERR_DRIVERINTERNALERROR;
5941 }
5942
5943
5944 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5945     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5946     /** FIXME: Resource tracking needs to be done,
5947     * The closes we can do to this is set the priorities of all managed textures low
5948     * and then reset them.
5949      ***********************************************************/
5950     FIXME("(%p) : stub\n", This);
5951     return WINED3D_OK;
5952 }
5953
5954 static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5955     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
5956
5957     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
5958     if(surface->Flags & SFLAG_DIBSECTION) {
5959         /* Release the DC */
5960         SelectObject(surface->hDC, surface->dib.holdbitmap);
5961         DeleteDC(surface->hDC);
5962         /* Release the DIB section */
5963         DeleteObject(surface->dib.DIBsection);
5964         surface->dib.bitmap_data = NULL;
5965         surface->resource.allocatedMemory = NULL;
5966         surface->Flags &= ~SFLAG_DIBSECTION;
5967     }
5968     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
5969     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
5970     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
5971         surface->pow2Width = pPresentationParameters->BackBufferWidth;
5972         surface->pow2Height = pPresentationParameters->BackBufferHeight;
5973     } else {
5974         surface->pow2Width = surface->pow2Height = 1;
5975         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
5976         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
5977     }
5978     if(surface->glDescription.textureName) {
5979         ENTER_GL();
5980         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5981         glDeleteTextures(1, &surface->glDescription.textureName);
5982         LEAVE_GL();
5983         surface->glDescription.textureName = 0;
5984         surface->Flags &= ~SFLAG_CLIENT;
5985     }
5986     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
5987        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
5988         surface->Flags |= SFLAG_NONPOW2;
5989     } else  {
5990         surface->Flags &= ~SFLAG_NONPOW2;
5991     }
5992     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
5993     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
5994 }
5995
5996 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5997     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5998     IWineD3DSwapChainImpl *swapchain;
5999     HRESULT hr;
6000     BOOL DisplayModeChanged = FALSE;
6001     WINED3DDISPLAYMODE mode;
6002     TRACE("(%p)\n", This);
6003
6004     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6005     if(FAILED(hr)) {
6006         ERR("Failed to get the first implicit swapchain\n");
6007         return hr;
6008     }
6009
6010     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6011      * on an existing gl context, so there's no real need for recreation.
6012      *
6013      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6014      *
6015      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6016      */
6017     TRACE("New params:\n");
6018     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
6019     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
6020     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
6021     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
6022     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
6023     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
6024     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
6025     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
6026     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
6027     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6028     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
6029     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
6030     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
6031
6032     /* No special treatment of these parameters. Just store them */
6033     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
6034     swapchain->presentParms.Flags = pPresentationParameters->Flags;
6035     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
6036     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
6037
6038     /* What to do about these? */
6039     if(pPresentationParameters->BackBufferCount != 0 &&
6040         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6041         ERR("Cannot change the back buffer count yet\n");
6042     }
6043     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6044         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6045         ERR("Cannot change the back buffer format yet\n");
6046     }
6047     if(pPresentationParameters->hDeviceWindow != NULL &&
6048         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6049         ERR("Cannot change the device window yet\n");
6050     }
6051     if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
6052         ERR("What do do about a changed auto depth stencil parameter?\n");
6053     }
6054
6055     if(pPresentationParameters->Windowed) {
6056         mode.Width = swapchain->orig_width;
6057         mode.Height = swapchain->orig_height;
6058         mode.RefreshRate = 0;
6059         mode.Format = swapchain->presentParms.BackBufferFormat;
6060     } else {
6061         mode.Width = pPresentationParameters->BackBufferWidth;
6062         mode.Height = pPresentationParameters->BackBufferHeight;
6063         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
6064         mode.Format = swapchain->presentParms.BackBufferFormat;
6065     }
6066
6067     /* Should Width == 800 && Height == 0 set 800x600? */
6068     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
6069        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6070         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6071     {
6072         WINED3DVIEWPORT vp;
6073         int i;
6074
6075         vp.X = 0;
6076         vp.Y = 0;
6077         vp.Width = pPresentationParameters->BackBufferWidth;
6078         vp.Height = pPresentationParameters->BackBufferHeight;
6079         vp.MinZ = 0;
6080         vp.MaxZ = 1;
6081
6082         if(!pPresentationParameters->Windowed) {
6083             DisplayModeChanged = TRUE;
6084         }
6085         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
6086         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
6087
6088         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
6089         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
6090             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
6091         }
6092
6093         /* Now set the new viewport */
6094         IWineD3DDevice_SetViewport(iface, &vp);
6095     }
6096
6097     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
6098        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
6099         DisplayModeChanged) {
6100
6101         /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
6102         if(!pPresentationParameters->Windowed) {
6103             IWineD3DDevice_SetFullscreen(iface, TRUE);
6104         }
6105
6106         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6107
6108         /* Switching out of fullscreen mode? First set the original res, then change the window */
6109         if(pPresentationParameters->Windowed) {
6110             IWineD3DDevice_SetFullscreen(iface, FALSE);
6111         }
6112         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
6113     }
6114
6115     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6116     return WINED3D_OK;
6117 }
6118
6119 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6120     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6121     /** FIXME: always true at the moment **/
6122     if(!bEnableDialogs) {
6123         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6124     }
6125     return WINED3D_OK;
6126 }
6127
6128
6129 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6130     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6131     TRACE("(%p) : pParameters %p\n", This, pParameters);
6132
6133     *pParameters = This->createParms;
6134     return WINED3D_OK;
6135 }
6136
6137 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6138     IWineD3DSwapChain *swapchain;
6139     HRESULT hrc = WINED3D_OK;
6140
6141     TRACE("Relaying  to swapchain\n");
6142
6143     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6144         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6145         IWineD3DSwapChain_Release(swapchain);
6146     }
6147     return;
6148 }
6149
6150 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6151     IWineD3DSwapChain *swapchain;
6152     HRESULT hrc = WINED3D_OK;
6153
6154     TRACE("Relaying  to swapchain\n");
6155
6156     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6157         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6158         IWineD3DSwapChain_Release(swapchain);
6159     }
6160     return;
6161 }
6162
6163
6164 /** ********************************************************
6165 *   Notification functions
6166 ** ********************************************************/
6167 /** This function must be called in the release of a resource when ref == 0,
6168 * the contents of resource must still be correct,
6169 * any handels to other resource held by the caller must be closed
6170 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6171  *****************************************************/
6172 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6173     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6174     ResourceList* resourceList;
6175
6176     TRACE("(%p) : resource %p\n", This, resource);
6177     /* add a new texture to the frot of the linked list */
6178     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6179     resourceList->resource = resource;
6180
6181     /* Get the old head */
6182     resourceList->next = This->resources;
6183
6184     This->resources = resourceList;
6185     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6186
6187     return;
6188 }
6189
6190 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6191     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6192     ResourceList* resourceList = NULL;
6193     ResourceList* previousResourceList = NULL;
6194     
6195     TRACE("(%p) : resource %p\n", This, resource);
6196
6197     resourceList = This->resources;
6198
6199     while (resourceList != NULL) {
6200         if(resourceList->resource == resource) break;
6201         previousResourceList = resourceList;
6202         resourceList = resourceList->next;
6203     }
6204
6205     if (resourceList == NULL) {
6206         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6207         return;
6208     } else {
6209             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6210     }
6211     /* make sure we don't leave a hole in the list */
6212     if (previousResourceList != NULL) {
6213         previousResourceList->next = resourceList->next;
6214     } else {
6215         This->resources = resourceList->next;
6216     }
6217
6218     return;
6219 }
6220
6221
6222 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6223     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6224     int counter;
6225
6226     TRACE("(%p) : resource %p\n", This, resource);
6227     switch(IWineD3DResource_GetType(resource)){
6228         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6229         case WINED3DRTYPE_SURFACE: {
6230             unsigned int i;
6231
6232             /* Cleanup any FBO attachments */
6233             for (i = 0; i < GL_LIMITS(buffers); ++i) {
6234                 if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) {
6235                     bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6236                     set_render_target_fbo(iface, i, NULL);
6237                     This->fbo_color_attachments[i] = NULL;
6238                 }
6239             }
6240             if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) {
6241                 bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
6242                 set_depth_stencil_fbo(iface, NULL);
6243                 This->fbo_depth_attachment = NULL;
6244             }
6245
6246             break;
6247         }
6248
6249         case WINED3DRTYPE_TEXTURE:
6250         case WINED3DRTYPE_CUBETEXTURE:
6251         case WINED3DRTYPE_VOLUMETEXTURE:
6252                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
6253                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6254                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6255                         This->stateBlock->textures[counter] = NULL;
6256                     }
6257                     if (This->updateStateBlock != This->stateBlock ){
6258                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6259                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6260                             This->updateStateBlock->textures[counter] = NULL;
6261                         }
6262                     }
6263                 }
6264         break;
6265         case WINED3DRTYPE_VOLUME:
6266         /* TODO: nothing really? */
6267         break;
6268         case WINED3DRTYPE_VERTEXBUFFER:
6269         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6270         {
6271             int streamNumber;
6272             TRACE("Cleaning up stream pointers\n");
6273
6274             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6275                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6276                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6277                 */
6278                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6279                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6280                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6281                         This->updateStateBlock->streamSource[streamNumber] = 0;
6282                         /* Set changed flag? */
6283                     }
6284                 }
6285                 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) */
6286                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6287                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6288                         This->stateBlock->streamSource[streamNumber] = 0;
6289                     }
6290                 }
6291 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6292                  else { /* This shouldn't happen */
6293                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6294                 }
6295 #endif
6296
6297             }
6298         }
6299         break;
6300         case WINED3DRTYPE_INDEXBUFFER:
6301         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6302         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6303             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6304                 This->updateStateBlock->pIndexData =  NULL;
6305             }
6306         }
6307         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6308             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6309                 This->stateBlock->pIndexData =  NULL;
6310             }
6311         }
6312
6313         break;
6314         default:
6315         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6316         break;
6317     }
6318
6319
6320     /* Remove the resoruce from the resourceStore */
6321     IWineD3DDeviceImpl_RemoveResource(iface, resource);
6322
6323     TRACE("Resource released\n");
6324
6325 }
6326
6327 /**********************************************************
6328  * IWineD3DDevice VTbl follows
6329  **********************************************************/
6330
6331 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6332 {
6333     /*** IUnknown methods ***/
6334     IWineD3DDeviceImpl_QueryInterface,
6335     IWineD3DDeviceImpl_AddRef,
6336     IWineD3DDeviceImpl_Release,
6337     /*** IWineD3DDevice methods ***/
6338     IWineD3DDeviceImpl_GetParent,
6339     /*** Creation methods**/
6340     IWineD3DDeviceImpl_CreateVertexBuffer,
6341     IWineD3DDeviceImpl_CreateIndexBuffer,
6342     IWineD3DDeviceImpl_CreateStateBlock,
6343     IWineD3DDeviceImpl_CreateSurface,
6344     IWineD3DDeviceImpl_CreateTexture,
6345     IWineD3DDeviceImpl_CreateVolumeTexture,
6346     IWineD3DDeviceImpl_CreateVolume,
6347     IWineD3DDeviceImpl_CreateCubeTexture,
6348     IWineD3DDeviceImpl_CreateQuery,
6349     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6350     IWineD3DDeviceImpl_CreateVertexDeclaration,
6351     IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF,
6352     IWineD3DDeviceImpl_CreateVertexShader,
6353     IWineD3DDeviceImpl_CreatePixelShader,
6354     IWineD3DDeviceImpl_CreatePalette,
6355     /*** Odd functions **/
6356     IWineD3DDeviceImpl_Init3D,
6357     IWineD3DDeviceImpl_Uninit3D,
6358     IWineD3DDeviceImpl_SetFullscreen,
6359     IWineD3DDeviceImpl_SetMultithreaded,
6360     IWineD3DDeviceImpl_EvictManagedResources,
6361     IWineD3DDeviceImpl_GetAvailableTextureMem,
6362     IWineD3DDeviceImpl_GetBackBuffer,
6363     IWineD3DDeviceImpl_GetCreationParameters,
6364     IWineD3DDeviceImpl_GetDeviceCaps,
6365     IWineD3DDeviceImpl_GetDirect3D,
6366     IWineD3DDeviceImpl_GetDisplayMode,
6367     IWineD3DDeviceImpl_SetDisplayMode,
6368     IWineD3DDeviceImpl_GetHWND,
6369     IWineD3DDeviceImpl_SetHWND,
6370     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6371     IWineD3DDeviceImpl_GetRasterStatus,
6372     IWineD3DDeviceImpl_GetSwapChain,
6373     IWineD3DDeviceImpl_Reset,
6374     IWineD3DDeviceImpl_SetDialogBoxMode,
6375     IWineD3DDeviceImpl_SetCursorProperties,
6376     IWineD3DDeviceImpl_SetCursorPosition,
6377     IWineD3DDeviceImpl_ShowCursor,
6378     IWineD3DDeviceImpl_TestCooperativeLevel,
6379     /*** Getters and setters **/
6380     IWineD3DDeviceImpl_SetClipPlane,
6381     IWineD3DDeviceImpl_GetClipPlane,
6382     IWineD3DDeviceImpl_SetClipStatus,
6383     IWineD3DDeviceImpl_GetClipStatus,
6384     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6385     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6386     IWineD3DDeviceImpl_SetDepthStencilSurface,
6387     IWineD3DDeviceImpl_GetDepthStencilSurface,
6388     IWineD3DDeviceImpl_SetFVF,
6389     IWineD3DDeviceImpl_GetFVF,
6390     IWineD3DDeviceImpl_SetGammaRamp,
6391     IWineD3DDeviceImpl_GetGammaRamp,
6392     IWineD3DDeviceImpl_SetIndices,
6393     IWineD3DDeviceImpl_GetIndices,
6394     IWineD3DDeviceImpl_SetBaseVertexIndex,
6395     IWineD3DDeviceImpl_GetBaseVertexIndex,
6396     IWineD3DDeviceImpl_SetLight,
6397     IWineD3DDeviceImpl_GetLight,
6398     IWineD3DDeviceImpl_SetLightEnable,
6399     IWineD3DDeviceImpl_GetLightEnable,
6400     IWineD3DDeviceImpl_SetMaterial,
6401     IWineD3DDeviceImpl_GetMaterial,
6402     IWineD3DDeviceImpl_SetNPatchMode,
6403     IWineD3DDeviceImpl_GetNPatchMode,
6404     IWineD3DDeviceImpl_SetPaletteEntries,
6405     IWineD3DDeviceImpl_GetPaletteEntries,
6406     IWineD3DDeviceImpl_SetPixelShader,
6407     IWineD3DDeviceImpl_GetPixelShader,
6408     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6409     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6410     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6411     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6412     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6413     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6414     IWineD3DDeviceImpl_SetRenderState,
6415     IWineD3DDeviceImpl_GetRenderState,
6416     IWineD3DDeviceImpl_SetRenderTarget,
6417     IWineD3DDeviceImpl_GetRenderTarget,
6418     IWineD3DDeviceImpl_SetFrontBackBuffers,
6419     IWineD3DDeviceImpl_SetSamplerState,
6420     IWineD3DDeviceImpl_GetSamplerState,
6421     IWineD3DDeviceImpl_SetScissorRect,
6422     IWineD3DDeviceImpl_GetScissorRect,
6423     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6424     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6425     IWineD3DDeviceImpl_SetStreamSource,
6426     IWineD3DDeviceImpl_GetStreamSource,
6427     IWineD3DDeviceImpl_SetStreamSourceFreq,
6428     IWineD3DDeviceImpl_GetStreamSourceFreq,
6429     IWineD3DDeviceImpl_SetTexture,
6430     IWineD3DDeviceImpl_GetTexture,
6431     IWineD3DDeviceImpl_SetTextureStageState,
6432     IWineD3DDeviceImpl_GetTextureStageState,
6433     IWineD3DDeviceImpl_SetTransform,
6434     IWineD3DDeviceImpl_GetTransform,
6435     IWineD3DDeviceImpl_SetVertexDeclaration,
6436     IWineD3DDeviceImpl_GetVertexDeclaration,
6437     IWineD3DDeviceImpl_SetVertexShader,
6438     IWineD3DDeviceImpl_GetVertexShader,
6439     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6440     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6441     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6442     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6443     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6444     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6445     IWineD3DDeviceImpl_SetViewport,
6446     IWineD3DDeviceImpl_GetViewport,
6447     IWineD3DDeviceImpl_MultiplyTransform,
6448     IWineD3DDeviceImpl_ValidateDevice,
6449     IWineD3DDeviceImpl_ProcessVertices,
6450     /*** State block ***/
6451     IWineD3DDeviceImpl_BeginStateBlock,
6452     IWineD3DDeviceImpl_EndStateBlock,
6453     /*** Scene management ***/
6454     IWineD3DDeviceImpl_BeginScene,
6455     IWineD3DDeviceImpl_EndScene,
6456     IWineD3DDeviceImpl_Present,
6457     IWineD3DDeviceImpl_Clear,
6458     /*** Drawing ***/
6459     IWineD3DDeviceImpl_DrawPrimitive,
6460     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6461     IWineD3DDeviceImpl_DrawPrimitiveUP,
6462     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6463     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6464     IWineD3DDeviceImpl_DrawRectPatch,
6465     IWineD3DDeviceImpl_DrawTriPatch,
6466     IWineD3DDeviceImpl_DeletePatch,
6467     IWineD3DDeviceImpl_ColorFill,
6468     IWineD3DDeviceImpl_UpdateTexture,
6469     IWineD3DDeviceImpl_UpdateSurface,
6470     IWineD3DDeviceImpl_GetFrontBufferData,
6471     /*** object tracking ***/
6472     IWineD3DDeviceImpl_ResourceReleased
6473 };
6474
6475
6476 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6477     WINED3DRS_ALPHABLENDENABLE   ,
6478     WINED3DRS_ALPHAFUNC          ,
6479     WINED3DRS_ALPHAREF           ,
6480     WINED3DRS_ALPHATESTENABLE    ,
6481     WINED3DRS_BLENDOP            ,
6482     WINED3DRS_COLORWRITEENABLE   ,
6483     WINED3DRS_DESTBLEND          ,
6484     WINED3DRS_DITHERENABLE       ,
6485     WINED3DRS_FILLMODE           ,
6486     WINED3DRS_FOGDENSITY         ,
6487     WINED3DRS_FOGEND             ,
6488     WINED3DRS_FOGSTART           ,
6489     WINED3DRS_LASTPIXEL          ,
6490     WINED3DRS_SHADEMODE          ,
6491     WINED3DRS_SRCBLEND           ,
6492     WINED3DRS_STENCILENABLE      ,
6493     WINED3DRS_STENCILFAIL        ,
6494     WINED3DRS_STENCILFUNC        ,
6495     WINED3DRS_STENCILMASK        ,
6496     WINED3DRS_STENCILPASS        ,
6497     WINED3DRS_STENCILREF         ,
6498     WINED3DRS_STENCILWRITEMASK   ,
6499     WINED3DRS_STENCILZFAIL       ,
6500     WINED3DRS_TEXTUREFACTOR      ,
6501     WINED3DRS_WRAP0              ,
6502     WINED3DRS_WRAP1              ,
6503     WINED3DRS_WRAP2              ,
6504     WINED3DRS_WRAP3              ,
6505     WINED3DRS_WRAP4              ,
6506     WINED3DRS_WRAP5              ,
6507     WINED3DRS_WRAP6              ,
6508     WINED3DRS_WRAP7              ,
6509     WINED3DRS_ZENABLE            ,
6510     WINED3DRS_ZFUNC              ,
6511     WINED3DRS_ZWRITEENABLE
6512 };
6513
6514 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6515     WINED3DTSS_ADDRESSW              ,
6516     WINED3DTSS_ALPHAARG0             ,
6517     WINED3DTSS_ALPHAARG1             ,
6518     WINED3DTSS_ALPHAARG2             ,
6519     WINED3DTSS_ALPHAOP               ,
6520     WINED3DTSS_BUMPENVLOFFSET        ,
6521     WINED3DTSS_BUMPENVLSCALE         ,
6522     WINED3DTSS_BUMPENVMAT00          ,
6523     WINED3DTSS_BUMPENVMAT01          ,
6524     WINED3DTSS_BUMPENVMAT10          ,
6525     WINED3DTSS_BUMPENVMAT11          ,
6526     WINED3DTSS_COLORARG0             ,
6527     WINED3DTSS_COLORARG1             ,
6528     WINED3DTSS_COLORARG2             ,
6529     WINED3DTSS_COLOROP               ,
6530     WINED3DTSS_RESULTARG             ,
6531     WINED3DTSS_TEXCOORDINDEX         ,
6532     WINED3DTSS_TEXTURETRANSFORMFLAGS
6533 };
6534
6535 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6536     WINED3DSAMP_ADDRESSU         ,
6537     WINED3DSAMP_ADDRESSV         ,
6538     WINED3DSAMP_ADDRESSW         ,
6539     WINED3DSAMP_BORDERCOLOR      ,
6540     WINED3DSAMP_MAGFILTER        ,
6541     WINED3DSAMP_MINFILTER        ,
6542     WINED3DSAMP_MIPFILTER        ,
6543     WINED3DSAMP_MIPMAPLODBIAS    ,
6544     WINED3DSAMP_MAXMIPLEVEL      ,
6545     WINED3DSAMP_MAXANISOTROPY    ,
6546     WINED3DSAMP_SRGBTEXTURE      ,
6547     WINED3DSAMP_ELEMENTINDEX
6548 };
6549
6550 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6551     WINED3DRS_AMBIENT                       ,
6552     WINED3DRS_AMBIENTMATERIALSOURCE         ,
6553     WINED3DRS_CLIPPING                      ,
6554     WINED3DRS_CLIPPLANEENABLE               ,
6555     WINED3DRS_COLORVERTEX                   ,
6556     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
6557     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
6558     WINED3DRS_FOGDENSITY                    ,
6559     WINED3DRS_FOGEND                        ,
6560     WINED3DRS_FOGSTART                      ,
6561     WINED3DRS_FOGTABLEMODE                  ,
6562     WINED3DRS_FOGVERTEXMODE                 ,
6563     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
6564     WINED3DRS_LIGHTING                      ,
6565     WINED3DRS_LOCALVIEWER                   ,
6566     WINED3DRS_MULTISAMPLEANTIALIAS          ,
6567     WINED3DRS_MULTISAMPLEMASK               ,
6568     WINED3DRS_NORMALIZENORMALS              ,
6569     WINED3DRS_PATCHEDGESTYLE                ,
6570     WINED3DRS_POINTSCALE_A                  ,
6571     WINED3DRS_POINTSCALE_B                  ,
6572     WINED3DRS_POINTSCALE_C                  ,
6573     WINED3DRS_POINTSCALEENABLE              ,
6574     WINED3DRS_POINTSIZE                     ,
6575     WINED3DRS_POINTSIZE_MAX                 ,
6576     WINED3DRS_POINTSIZE_MIN                 ,
6577     WINED3DRS_POINTSPRITEENABLE             ,
6578     WINED3DRS_RANGEFOGENABLE                ,
6579     WINED3DRS_SPECULARMATERIALSOURCE        ,
6580     WINED3DRS_TWEENFACTOR                   ,
6581     WINED3DRS_VERTEXBLEND
6582 };
6583
6584 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6585     WINED3DTSS_TEXCOORDINDEX         ,
6586     WINED3DTSS_TEXTURETRANSFORMFLAGS
6587 };
6588
6589 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6590     WINED3DSAMP_DMAPOFFSET
6591 };
6592
6593 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
6594     DWORD rep = StateTable[state].representative;
6595     DWORD idx;
6596     BYTE shift;
6597     UINT i;
6598     WineD3DContext *context;
6599
6600     if(!rep) return;
6601     for(i = 0; i < This->numContexts; i++) {
6602         context = This->contexts[i];
6603         if(isStateDirty(context, rep)) continue;
6604
6605         context->dirtyArray[context->numDirtyEntries++] = rep;
6606         idx = rep >> 5;
6607         shift = rep & 0x1f;
6608         context->isStateDirty[idx] |= (1 << shift);
6609     }
6610 }