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