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