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