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