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