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