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