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