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