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