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