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