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