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